[hornetq-commits] JBoss hornetq SVN: r10740 - in trunk: hornetq-commons/src/main/java/org/hornetq/api/core and 12 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Thu May 26 11:06:41 EDT 2011
Author: borges
Date: 2011-05-26 11:06:40 -0400 (Thu, 26 May 2011)
New Revision: 10740
Added:
trunk/hornetq-commons/src/main/java/org/hornetq/api/core/PropertyConversionException.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/Base64.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentHashSet.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentSet.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/HornetQThreadFactory.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/ReusableLatch.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/TypedProperties.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUID.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDGenerator.java
trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDTimer.java
trunk/hornetq-journal/
trunk/hornetq-journal/pom.xml
trunk/hornetq-journal/src/
trunk/hornetq-journal/src/main/
trunk/hornetq-journal/src/main/java/
trunk/hornetq-journal/src/main/java/org/
trunk/hornetq-journal/src/main/java/org/hornetq/
trunk/hornetq-journal/src/main/java/org/hornetq/core/
trunk/hornetq-journal/src/main/java/org/hornetq/core/asyncio/
trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/
trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/JournalConstants.java
Removed:
trunk/hornetq-core/src/main/java/org/hornetq/api/core/PropertyConversionException.java
trunk/hornetq-core/src/main/java/org/hornetq/core/asyncio/
trunk/hornetq-core/src/main/java/org/hornetq/core/journal/
trunk/hornetq-core/src/main/java/org/hornetq/utils/Base64.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentHashSet.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentSet.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/HornetQThreadFactory.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/ReusableLatch.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/TypedProperties.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/UUID.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDGenerator.java
trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDTimer.java
Modified:
trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AIOSequentialFileFactory.java
trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AbstractSequentialFileFactory.java
trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/NIOSequentialFileFactory.java
trunk/pom.xml
Log:
HORNETQ-698 Create new hornetq-journals package, move files around to suit new project.
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/api/core/PropertyConversionException.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/api/core/PropertyConversionException.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/api/core/PropertyConversionException.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/api/core/PropertyConversionException.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.api.core;
+
+/**
+ * A PropertyConversionException is thrown by Message methods
+ * when a property can not be converted to the expected type.
+ *
+ * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
+ *
+ * @see Message
+ *
+ */
+public class PropertyConversionException extends RuntimeException
+{
+
+ // Constants -----------------------------------------------------
+
+ private static final long serialVersionUID = -3010008708334904332L;
+
+ // Attributes ----------------------------------------------------
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+
+ public PropertyConversionException(final String message)
+ {
+ super(message);
+ }
+
+ // Public --------------------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/Base64.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/Base64.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/Base64.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/Base64.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,2350 @@
+package org.hornetq.utils;
+
+/**
+ * <p>Encodes and decodes to and from Base64 notation.</p>
+ * <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p>
+ *
+ * <p>The <tt>options</tt> parameter, which appears in a few places, is used to pass
+ * several pieces of information to the encoder. In the "higher level" methods such as
+ * encodeBytes( bytes, options ) the options parameter can be used to indicate such
+ * things as first gzipping the bytes before encoding them, not inserting linefeeds
+ * (though that breaks strict Base64 compatibility), and encoding using the URL-safe
+ * and Ordered dialects.</p>
+ *
+ * <p>The constants defined in Base64 can be OR-ed together to combine options, so you
+ * might make a call like this:</p>
+ *
+ * <code>String encoded = Base64.encodeBytes( mybytes, Base64.GZIP | Base64.DONT_BREAK_LINES );</code>
+ *
+ * <p>to compress the data before encoding it and then making the output have no newline characters.</p>
+ *
+ *
+ * <p>
+ * Change Log:
+ * </p>
+ * <ul>
+ * <li>v2.2.2 - Fixed encodeFileToFile and decodeFileToFile to use the
+ * Base64.InputStream class to encode and decode on the fly which uses
+ * less memory than encoding/decoding an entire file into memory before writing.</li>
+ * <li>v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug
+ * when using very small files (~< 40 bytes).</li>
+ * <li>v2.2 - Added some helper methods for encoding/decoding directly from
+ * one file to the next. Also added a main() method to support command line
+ * encoding/decoding from one file to the next. Also added these Base64 dialects:
+ * <ol>
+ * <li>The default is RFC3548 format.</li>
+ * <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates
+ * URL and file name friendly format as described in Section 4 of RFC3548.
+ * http://www.faqs.org/rfcs/rfc3548.html</li>
+ * <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates
+ * URL and file name friendly format that preserves lexical ordering as described
+ * in http://www.faqs.org/qa/rfcc-1940.html</li>
+ * </ol>
+ * Special thanks to Jim Kellerman at <a href="http://www.powerset.com/">http://www.powerset.com/</a>
+ * for contributing the new Base64 dialects.
+ * </li>
+ *
+ * <li>v2.1 - Cleaned up javadoc comments and unused variables and methods. Added
+ * some convenience methods for reading and writing to and from files.</li>
+ * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems
+ * with other encodings (like EBCDIC).</li>
+ * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
+ * encoded data was a single byte.</li>
+ * <li>v2.0 - I got rid of methods that used booleans to set options.
+ * Now everything is more consolidated and cleaner. The code now detects
+ * when data that's being decoded is gzip-compressed and will decompress it
+ * automatically. Generally things are cleaner. You'll probably have to
+ * change some method calls that you were making to support the new
+ * options format (<tt>int</tt>s that you "OR" together).</li>
+ * <li>v1.5.1 - Fixed bug when decompressing and decoding to a
+ * byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.
+ * Added the ability to "suspend" encoding in the Output Stream so
+ * you can turn on and off the encoding if you need to embed base64
+ * data in an otherwise "normal" stream (like an XML file).</li>
+ * <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself.
+ * This helps when using GZIP streams.
+ * Added the ability to GZip-compress objects before encoding them.</li>
+ * <li>v1.4 - Added helper methods to read/write files.</li>
+ * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
+ * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream
+ * where last buffer being read, if not completely full, was not returned.</li>
+ * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.</li>
+ * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
+ * </ul>
+ *
+ * <p>
+ * I am placing this code in the Public Domain. Do with it as you will.
+ * This software comes with no guarantees or warranties but with
+ * plenty of well-wishing instead!
+ * Please visit <a href="http://iharder.net/base64">http://iharder.net/base64</a>
+ * periodically to check for updates or to contribute improvements.
+ * </p>
+ *
+ * @author Robert Harder
+ * @author rob at iharder.net
+ * @version 2.2.2
+ */
+public class Base64
+{
+
+ /* ******** P U B L I C F I E L D S ******** */
+
+ /** No options specified. Value is zero. */
+ public final static int NO_OPTIONS = 0;
+
+ /** Specify encoding. */
+ public final static int ENCODE = 1;
+
+ /** Specify decoding. */
+ public final static int DECODE = 0;
+
+ /** Specify that data should be gzip-compressed. */
+ public final static int GZIP = 2;
+
+ /** Don't break lines when encoding (violates strict Base64 specification) */
+ public final static int DONT_BREAK_LINES = 8;
+
+ /**
+ * Encode using Base64-like encoding that is URL- and Filename-safe as described
+ * in Section 4 of RFC3548:
+ * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
+ * It is important to note that data encoded this way is <em>not</em> officially valid Base64,
+ * or at the very least should not be called Base64 without also specifying that is
+ * was encoded using the URL- and Filename-safe dialect.
+ */
+ public final static int URL_SAFE = 16;
+
+ /**
+ * Encode using the special "ordered" dialect of Base64 described here:
+ * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ public final static int ORDERED = 32;
+
+ /* ******** P R I V A T E F I E L D S ******** */
+
+ /** Maximum line length (76) of Base64 output. */
+ private final static int MAX_LINE_LENGTH = 76;
+
+ /** The equals sign (=) as a byte. */
+ private final static byte EQUALS_SIGN = (byte)'=';
+
+ /** The new line character (\n) as a byte. */
+ private final static byte NEW_LINE = (byte)'\n';
+
+ /** Preferred encoding. */
+ private final static String PREFERRED_ENCODING = "UTF-8";
+
+ // I think I end up not using the BAD_ENCODING indicator.
+ // private final static byte BAD_ENCODING = -9; // Indicates error in encoding
+ private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
+
+ private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
+
+ /* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
+
+ /** The 64 valid Base64 values. */
+ // private final static byte[] ALPHABET;
+ /* Host platform me be something funny like EBCDIC, so we hardcode these values. */
+ private final static byte[] _STANDARD_ALPHABET = { (byte)'A',
+ (byte)'B',
+ (byte)'C',
+ (byte)'D',
+ (byte)'E',
+ (byte)'F',
+ (byte)'G',
+ (byte)'H',
+ (byte)'I',
+ (byte)'J',
+ (byte)'K',
+ (byte)'L',
+ (byte)'M',
+ (byte)'N',
+ (byte)'O',
+ (byte)'P',
+ (byte)'Q',
+ (byte)'R',
+ (byte)'S',
+ (byte)'T',
+ (byte)'U',
+ (byte)'V',
+ (byte)'W',
+ (byte)'X',
+ (byte)'Y',
+ (byte)'Z',
+ (byte)'a',
+ (byte)'b',
+ (byte)'c',
+ (byte)'d',
+ (byte)'e',
+ (byte)'f',
+ (byte)'g',
+ (byte)'h',
+ (byte)'i',
+ (byte)'j',
+ (byte)'k',
+ (byte)'l',
+ (byte)'m',
+ (byte)'n',
+ (byte)'o',
+ (byte)'p',
+ (byte)'q',
+ (byte)'r',
+ (byte)'s',
+ (byte)'t',
+ (byte)'u',
+ (byte)'v',
+ (byte)'w',
+ (byte)'x',
+ (byte)'y',
+ (byte)'z',
+ (byte)'0',
+ (byte)'1',
+ (byte)'2',
+ (byte)'3',
+ (byte)'4',
+ (byte)'5',
+ (byte)'6',
+ (byte)'7',
+ (byte)'8',
+ (byte)'9',
+ (byte)'+',
+ (byte)'/' };
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value
+ * or a negative number indicating some other meaning.
+ **/
+ private final static byte[] _STANDARD_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5,
+ -5, // Whitespace: Tab and Linefeed
+ -9,
+ -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 14 - 26
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 33 - 42
+ 62, // Plus sign at decimal 43
+ -9,
+ -9,
+ -9, // Decimal 44 - 46
+ 63, // Slash at decimal 47
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61, // Numbers zero through nine
+ -9,
+ -9,
+ -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,
+ -9,
+ -9, // Decimal 62 - 64
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13, // Letters 'A' through 'N'
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25, // Letters 'O' through 'Z'
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 91 - 96
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38, // Letters 'a' through 'm'
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51, // Letters 'n' through 'z'
+ -9,
+ -9,
+ -9,
+ -9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
+ * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
+ * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
+ */
+ private final static byte[] _URL_SAFE_ALPHABET = { (byte)'A',
+ (byte)'B',
+ (byte)'C',
+ (byte)'D',
+ (byte)'E',
+ (byte)'F',
+ (byte)'G',
+ (byte)'H',
+ (byte)'I',
+ (byte)'J',
+ (byte)'K',
+ (byte)'L',
+ (byte)'M',
+ (byte)'N',
+ (byte)'O',
+ (byte)'P',
+ (byte)'Q',
+ (byte)'R',
+ (byte)'S',
+ (byte)'T',
+ (byte)'U',
+ (byte)'V',
+ (byte)'W',
+ (byte)'X',
+ (byte)'Y',
+ (byte)'Z',
+ (byte)'a',
+ (byte)'b',
+ (byte)'c',
+ (byte)'d',
+ (byte)'e',
+ (byte)'f',
+ (byte)'g',
+ (byte)'h',
+ (byte)'i',
+ (byte)'j',
+ (byte)'k',
+ (byte)'l',
+ (byte)'m',
+ (byte)'n',
+ (byte)'o',
+ (byte)'p',
+ (byte)'q',
+ (byte)'r',
+ (byte)'s',
+ (byte)'t',
+ (byte)'u',
+ (byte)'v',
+ (byte)'w',
+ (byte)'x',
+ (byte)'y',
+ (byte)'z',
+ (byte)'0',
+ (byte)'1',
+ (byte)'2',
+ (byte)'3',
+ (byte)'4',
+ (byte)'5',
+ (byte)'6',
+ (byte)'7',
+ (byte)'8',
+ (byte)'9',
+ (byte)'-',
+ (byte)'_' };
+
+ /**
+ * Used in decoding URL- and Filename-safe dialects of Base64.
+ */
+ private final static byte[] _URL_SAFE_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5,
+ -5, // Whitespace: Tab and Linefeed
+ -9,
+ -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 14 - 26
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 62, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61, // Numbers zero through nine
+ -9,
+ -9,
+ -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,
+ -9,
+ -9, // Decimal 62 - 64
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13, // Letters 'A' through 'N'
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25, // Letters 'O' through 'Z'
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 91 - 94
+ 63, // Underscore at decimal 95
+ -9, // Decimal 96
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38, // Letters 'a' through 'm'
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51, // Letters 'n' through 'z'
+ -9,
+ -9,
+ -9,
+ -9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ /* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * I don't get the point of this technique, but it is described here:
+ * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ private final static byte[] _ORDERED_ALPHABET = { (byte)'-',
+ (byte)'0',
+ (byte)'1',
+ (byte)'2',
+ (byte)'3',
+ (byte)'4',
+ (byte)'5',
+ (byte)'6',
+ (byte)'7',
+ (byte)'8',
+ (byte)'9',
+ (byte)'A',
+ (byte)'B',
+ (byte)'C',
+ (byte)'D',
+ (byte)'E',
+ (byte)'F',
+ (byte)'G',
+ (byte)'H',
+ (byte)'I',
+ (byte)'J',
+ (byte)'K',
+ (byte)'L',
+ (byte)'M',
+ (byte)'N',
+ (byte)'O',
+ (byte)'P',
+ (byte)'Q',
+ (byte)'R',
+ (byte)'S',
+ (byte)'T',
+ (byte)'U',
+ (byte)'V',
+ (byte)'W',
+ (byte)'X',
+ (byte)'Y',
+ (byte)'Z',
+ (byte)'_',
+ (byte)'a',
+ (byte)'b',
+ (byte)'c',
+ (byte)'d',
+ (byte)'e',
+ (byte)'f',
+ (byte)'g',
+ (byte)'h',
+ (byte)'i',
+ (byte)'j',
+ (byte)'k',
+ (byte)'l',
+ (byte)'m',
+ (byte)'n',
+ (byte)'o',
+ (byte)'p',
+ (byte)'q',
+ (byte)'r',
+ (byte)'s',
+ (byte)'t',
+ (byte)'u',
+ (byte)'v',
+ (byte)'w',
+ (byte)'x',
+ (byte)'y',
+ (byte)'z' };
+
+ /**
+ * Used in decoding the "ordered" dialect of Base64.
+ */
+ private final static byte[] _ORDERED_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5,
+ -5, // Whitespace: Tab and Linefeed
+ -9,
+ -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 14 - 26
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 0, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10, // Numbers zero through nine
+ -9,
+ -9,
+ -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,
+ -9,
+ -9, // Decimal 62 - 64
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23, // Letters 'A' through 'M'
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36, // Letters 'N' through 'Z'
+ -9,
+ -9,
+ -9,
+ -9, // Decimal 91 - 94
+ 37, // Underscore at decimal 95
+ -9, // Decimal 96
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50, // Letters 'a' through 'm'
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63, // Letters 'n' through 'z'
+ -9,
+ -9,
+ -9,
+ -9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ /* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
+
+ /**
+ * Returns one of the _SOMETHING_ALPHABET byte arrays depending on
+ * the options specified.
+ * It's possible, though silly, to specify ORDERED and URLSAFE
+ * in which case one of them will be picked, though there is
+ * no guarantee as to which one will be picked.
+ */
+ private final static byte[] getAlphabet(final int options)
+ {
+ if ((options & Base64.URL_SAFE) == Base64.URL_SAFE)
+ {
+ return Base64._URL_SAFE_ALPHABET;
+ }
+ else if ((options & Base64.ORDERED) == Base64.ORDERED)
+ {
+ return Base64._ORDERED_ALPHABET;
+ }
+ else
+ {
+ return Base64._STANDARD_ALPHABET;
+ }
+
+ } // end getAlphabet
+
+ /**
+ * Returns one of the _SOMETHING_DECODABET byte arrays depending on
+ * the options specified.
+ * It's possible, though silly, to specify ORDERED and URL_SAFE
+ * in which case one of them will be picked, though there is
+ * no guarantee as to which one will be picked.
+ */
+ private final static byte[] getDecodabet(final int options)
+ {
+ if ((options & Base64.URL_SAFE) == Base64.URL_SAFE)
+ {
+ return Base64._URL_SAFE_DECODABET;
+ }
+ else if ((options & Base64.ORDERED) == Base64.ORDERED)
+ {
+ return Base64._ORDERED_DECODABET;
+ }
+ else
+ {
+ return Base64._STANDARD_DECODABET;
+ }
+
+ } // end getAlphabet
+
+ /** Defeats instantiation. */
+ private Base64()
+ {
+ }
+
+ /**
+ * Encodes or decodes two files from the command line;
+ * <strong>feel free to delete this method (in fact you probably should)
+ * if you're embedding this code into a larger program.</strong>
+ */
+ public final static void main(final String[] args)
+ {
+ if (args.length < 3)
+ {
+ Base64.usage("Not enough arguments.");
+ } // end if: args.length < 3
+ else
+ {
+ String flag = args[0];
+ String infile = args[1];
+ String outfile = args[2];
+ if (flag.equals("-e"))
+ {
+ Base64.encodeFileToFile(infile, outfile);
+ } // end if: encode
+ else if (flag.equals("-d"))
+ {
+ Base64.decodeFileToFile(infile, outfile);
+ } // end else if: decode
+ else
+ {
+ Base64.usage("Unknown flag: " + flag);
+ } // end else
+ } // end else
+ } // end main
+
+ /**
+ * Prints command line usage.
+ *
+ * @param msg A message to include with usage info.
+ */
+ private final static void usage(final String msg)
+ {
+ System.err.println(msg);
+ System.err.println("Usage: java Base64 -e|-d inputfile outputfile");
+ } // end usage
+
+ /* ******** E N C O D I N G M E T H O D S ******** */
+
+ /**
+ * Encodes up to the first three bytes of array <var>threeBytes</var>
+ * and returns a four-byte array in Base64 notation.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.
+ * The array <var>threeBytes</var> needs only be as big as
+ * <var>numSigBytes</var>.
+ * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
+ *
+ * @param b4 A reusable byte array to reduce array instantiation
+ * @param threeBytes the array to convert
+ * @param numSigBytes the number of significant bytes in your array
+ * @return four byte array in Base64 notation.
+ * @since 1.5.1
+ */
+ private static byte[] encode3to4(final byte[] b4, final byte[] threeBytes, final int numSigBytes, final int options)
+ {
+ Base64.encode3to4(threeBytes, 0, numSigBytes, b4, 0, options);
+ return b4;
+ } // end encode3to4
+
+ /**
+ * <p>Encodes up to three bytes of the array <var>source</var>
+ * and writes the resulting four Base64 bytes to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 3 for
+ * the <var>source</var> array or <var>destOffset</var> + 4 for
+ * the <var>destination</var> array.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.</p>
+ * <p>This is the lowest level of the encoding methods with
+ * all possible parameters.</p>
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param numSigBytes the number of significant bytes in your array
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @return the <var>destination</var> array
+ * @since 1.3
+ */
+ private static byte[] encode3to4(final byte[] source,
+ final int srcOffset,
+ final int numSigBytes,
+ final byte[] destination,
+ final int destOffset,
+ final int options)
+ {
+ byte[] ALPHABET = Base64.getAlphabet(options);
+
+ // 1 2 3
+ // 01234567890123456789012345678901 Bit position
+ // --------000000001111111122222222 Array position from threeBytes
+ // --------| || || || | Six bit groups to index ALPHABET
+ // >>18 >>12 >> 6 >> 0 Right shift necessary
+ // 0x3f 0x3f 0x3f Additional AND
+
+ // Create buffer with zero-padding if there are only one or two
+ // significant bytes passed in the array.
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte to an int.
+ int inBuff = (numSigBytes > 0 ? source[srcOffset] << 24 >>> 8 : 0) | (numSigBytes > 1 ? source[srcOffset + 1] << 24 >>> 16
+ : 0) |
+ (numSigBytes > 2 ? source[srcOffset + 2] << 24 >>> 24 : 0);
+
+ switch (numSigBytes)
+ {
+ case 3:
+ destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+ destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
+ destination[destOffset + 2] = ALPHABET[inBuff >>> 6 & 0x3f];
+ destination[destOffset + 3] = ALPHABET[inBuff & 0x3f];
+ return destination;
+
+ case 2:
+ destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+ destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
+ destination[destOffset + 2] = ALPHABET[inBuff >>> 6 & 0x3f];
+ destination[destOffset + 3] = Base64.EQUALS_SIGN;
+ return destination;
+
+ case 1:
+ destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+ destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
+ destination[destOffset + 2] = Base64.EQUALS_SIGN;
+ destination[destOffset + 3] = Base64.EQUALS_SIGN;
+ return destination;
+
+ default:
+ return destination;
+ } // end switch
+ } // end encode3to4
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * The object is not GZip-compressed before being encoded.
+ *
+ * @param serializableObject The object to encode
+ * @return The Base64-encoded object
+ * @since 1.4
+ */
+ public static String encodeObject(final java.io.Serializable serializableObject)
+ {
+ return Base64.encodeObject(serializableObject, Base64.NO_OPTIONS);
+ } // end encodeObject
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param serializableObject The object to encode
+ * @param options Specified options
+ * @return The Base64-encoded object
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeObject(final java.io.Serializable serializableObject, final int options)
+ {
+ // Streams
+ java.io.ByteArrayOutputStream baos = null;
+ java.io.OutputStream b64os = null;
+ java.io.ObjectOutputStream oos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+
+ // Isolate options
+ int gzip = options & Base64.GZIP;
+ int dontBreakLines = options & Base64.DONT_BREAK_LINES;
+
+ try
+ {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream(baos, Base64.ENCODE | options);
+
+ // GZip?
+ if (gzip == Base64.GZIP)
+ {
+ gzos = new java.util.zip.GZIPOutputStream(b64os);
+ oos = new java.io.ObjectOutputStream(gzos);
+ } // end if: gzip
+ else
+ {
+ oos = new java.io.ObjectOutputStream(b64os);
+ }
+
+ oos.writeObject(serializableObject);
+ } // end try
+ catch (java.io.IOException e)
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try
+ {
+ oos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ gzos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ b64os.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ baos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String(baos.toByteArray(), Base64.PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String(baos.toByteArray());
+ } // end catch
+
+ } // end encode
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes(final byte[] source)
+ {
+ return Base64.encodeBytes(source, 0, source.length, Base64.NO_OPTIONS);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param options Specified options
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes(final byte[] source, final int options)
+ {
+ return Base64.encodeBytes(source, 0, source.length, options);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes(final byte[] source, final int off, final int len)
+ {
+ return Base64.encodeBytes(source, off, len, Base64.NO_OPTIONS);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @param options options alphabet type is pulled from this (standard, url-safe, ordered)
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes(final byte[] source, final int off, final int len, final int options)
+ {
+ // Isolate options
+ int dontBreakLines = options & Base64.DONT_BREAK_LINES;
+ int gzip = options & Base64.GZIP;
+
+ // Compress?
+ if (gzip == Base64.GZIP)
+ {
+ java.io.ByteArrayOutputStream baos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+ Base64.OutputStream b64os = null;
+
+ try
+ {
+ // GZip -> Base64 -> ByteArray
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream(baos, Base64.ENCODE | options);
+ gzos = new java.util.zip.GZIPOutputStream(b64os);
+
+ gzos.write(source, off, len);
+ gzos.close();
+ } // end try
+ catch (java.io.IOException e)
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try
+ {
+ gzos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ b64os.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ baos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String(baos.toByteArray(), Base64.PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String(baos.toByteArray());
+ } // end catch
+ } // end if: compress
+
+ // Else, don't compress. Better not to use streams at all then.
+ else
+ {
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
+
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[len43 + (len % 3 > 0 ? 4 : 0) // Account for padding
+ +
+ (breakLines ? len43 / Base64.MAX_LINE_LENGTH : 0)]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for (; d < len2; d += 3, e += 4)
+ {
+ Base64.encode3to4(source, d + off, 3, outBuff, e, options);
+
+ lineLength += 4;
+ if (breakLines && lineLength == Base64.MAX_LINE_LENGTH)
+ {
+ outBuff[e + 4] = Base64.NEW_LINE;
+ e++;
+ lineLength = 0;
+ } // end if: end of line
+ } // en dfor: each piece of array
+
+ if (d < len)
+ {
+ Base64.encode3to4(source, d + off, len - d, outBuff, e, options);
+ e += 4;
+ } // end if: some padding needed
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String(outBuff, 0, e, Base64.PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String(outBuff, 0, e);
+ } // end catch
+
+ } // end else: don't compress
+
+ } // end encodeBytes
+
+ /* ******** D E C O D I N G M E T H O D S ******** */
+
+ /**
+ * Decodes four bytes from array <var>source</var>
+ * and writes the resulting bytes (up to three of them)
+ * to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 4 for
+ * the <var>source</var> array or <var>destOffset</var> + 3 for
+ * the <var>destination</var> array.
+ * This method returns the actual number of bytes that
+ * were converted from the Base64 encoding.
+ * <p>This is the lowest level of the decoding methods with
+ * all possible parameters.</p>
+ *
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @param options alphabet type is pulled from this (standard, url-safe, ordered)
+ * @return the number of decoded bytes converted
+ * @since 1.3
+ */
+ private static int decode4to3(final byte[] source,
+ final int srcOffset,
+ final byte[] destination,
+ final int destOffset,
+ final int options)
+ {
+ byte[] DECODABET = Base64.getDecodabet(options);
+
+ // Example: Dk==
+ if (source[srcOffset + 2] == Base64.EQUALS_SIGN)
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
+ int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12;
+
+ destination[destOffset] = (byte)(outBuff >>> 16);
+ return 1;
+ }
+
+ // Example: DkL=
+ else if (source[srcOffset + 3] == Base64.EQUALS_SIGN)
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
+ int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12 |
+ (DECODABET[source[srcOffset + 2]] & 0xFF) << 6;
+
+ destination[destOffset] = (byte)(outBuff >>> 16);
+ destination[destOffset + 1] = (byte)(outBuff >>> 8);
+ return 2;
+ }
+
+ // Example: DkLE
+ else
+ {
+ try
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+ // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+ int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12 |
+ (DECODABET[source[srcOffset + 2]] & 0xFF) << 6 |
+ DECODABET[source[srcOffset + 3]] &
+ 0xFF;
+
+ destination[destOffset] = (byte)(outBuff >> 16);
+ destination[destOffset + 1] = (byte)(outBuff >> 8);
+ destination[destOffset + 2] = (byte)outBuff;
+
+ return 3;
+ }
+ catch (Exception e)
+ {
+ System.out.println("" + source[srcOffset] + ": " + DECODABET[source[srcOffset]]);
+ System.out.println("" + source[srcOffset + 1] + ": " + DECODABET[source[srcOffset + 1]]);
+ System.out.println("" + source[srcOffset + 2] + ": " + DECODABET[source[srcOffset + 2]]);
+ System.out.println("" + source[srcOffset + 3] + ": " + DECODABET[source[srcOffset + 3]]);
+ return -1;
+ } // end catch
+ }
+ } // end decodeToBytes
+
+ /**
+ * Very low-level access to decoding ASCII characters in
+ * the form of a byte array. Does not support automatically
+ * gunzipping or any other "fancy" features.
+ *
+ * @param source The Base64 encoded data
+ * @param off The offset of where to begin decoding
+ * @param len The length of characters to decode
+ * @return decoded data
+ * @since 1.3
+ */
+ public static byte[] decode(final byte[] source, final int off, final int len, final int options)
+ {
+ byte[] DECODABET = Base64.getDecodabet(options);
+
+ int len34 = len * 3 / 4;
+ byte[] outBuff = new byte[len34]; // Upper limit on size of output
+ int outBuffPosn = 0;
+
+ byte[] b4 = new byte[4];
+ int b4Posn = 0;
+ int i = 0;
+ byte sbiCrop = 0;
+ byte sbiDecode = 0;
+ for (i = off; i < off + len; i++)
+ {
+ sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
+ sbiDecode = DECODABET[sbiCrop];
+
+ if (sbiDecode >= Base64.WHITE_SPACE_ENC) // White space, Equals sign or better
+ {
+ if (sbiDecode >= Base64.EQUALS_SIGN_ENC)
+ {
+ b4[b4Posn++] = sbiCrop;
+ if (b4Posn > 3)
+ {
+ outBuffPosn += Base64.decode4to3(b4, 0, outBuff, outBuffPosn, options);
+ b4Posn = 0;
+
+ // If that was the equals sign, break out of 'for' loop
+ if (sbiCrop == Base64.EQUALS_SIGN)
+ {
+ break;
+ }
+ } // end if: quartet built
+
+ } // end if: equals sign or better
+
+ } // end if: white space, equals sign or better
+ else
+ {
+ System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
+ return null;
+ } // end else:
+ } // each input character
+
+ byte[] out = new byte[outBuffPosn];
+ System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
+ return out;
+ } // end decode
+
+ /**
+ * Decodes data from Base64 notation, automatically
+ * detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode(final String s)
+ {
+ return Base64.decode(s, Base64.NO_OPTIONS);
+ }
+
+ /**
+ * Decodes data from Base64 notation, automatically
+ * detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @param options encode options such as URL_SAFE
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode(final String s, final int options)
+ {
+ byte[] bytes;
+ try
+ {
+ bytes = s.getBytes(Base64.PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uee)
+ {
+ bytes = s.getBytes();
+ } // end catch
+ // </change>
+
+ // Decode
+ bytes = Base64.decode(bytes, 0, bytes.length, options);
+
+ // Check to see if it's gzip-compressed
+ // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+ if (bytes != null && bytes.length >= 4)
+ {
+
+ int head = bytes[0] & 0xff | bytes[1] << 8 & 0xff00;
+ if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head)
+ {
+ java.io.ByteArrayInputStream bais = null;
+ java.util.zip.GZIPInputStream gzis = null;
+ java.io.ByteArrayOutputStream baos = null;
+ byte[] buffer = new byte[2048];
+ int length = 0;
+
+ try
+ {
+ baos = new java.io.ByteArrayOutputStream();
+ bais = new java.io.ByteArrayInputStream(bytes);
+ gzis = new java.util.zip.GZIPInputStream(bais);
+
+ while ((length = gzis.read(buffer)) >= 0)
+ {
+ baos.write(buffer, 0, length);
+ } // end while: reading input
+
+ // No error? Get new bytes.
+ bytes = baos.toByteArray();
+
+ } // end try
+ catch (java.io.IOException e)
+ {
+ // Just return originally-decoded bytes
+ } // end catch
+ finally
+ {
+ try
+ {
+ baos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ gzis.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ bais.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ } // end if: gzipped
+ } // end if: bytes.length >= 2
+
+ return bytes;
+ } // end decode
+
+ /**
+ * Attempts to decode Base64 data and deserialize a Java
+ * Object within. Returns <tt>null</tt> if there was an error.
+ *
+ * @param encodedObject The Base64 data to decode
+ * @return The decoded and deserialized object
+ * @since 1.5
+ */
+ public static Object decodeToObject(final String encodedObject)
+ {
+ // Decode and gunzip if necessary
+ byte[] objBytes = Base64.decode(encodedObject);
+
+ java.io.ByteArrayInputStream bais = null;
+ java.io.ObjectInputStream ois = null;
+ Object obj = null;
+
+ try
+ {
+ bais = new java.io.ByteArrayInputStream(objBytes);
+ ois = new java.io.ObjectInputStream(bais);
+
+ obj = ois.readObject();
+ } // end try
+ catch (java.io.IOException e)
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ catch (java.lang.ClassNotFoundException e)
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ finally
+ {
+ try
+ {
+ bais.close();
+ }
+ catch (Exception e)
+ {
+ }
+ try
+ {
+ ois.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ return obj;
+ } // end decodeObject
+
+ /**
+ * Convenience method for encoding data to a file.
+ *
+ * @param dataToEncode byte array of data to encode in base64 form
+ * @param filename Filename for saving encoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean encodeToFile(final byte[] dataToEncode, final String filename)
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
+ bos.write(dataToEncode);
+ success = true;
+ } // end try
+ catch (java.io.IOException e)
+ {
+
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try
+ {
+ bos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ return success;
+ } // end encodeToFile
+
+ /**
+ * Convenience method for decoding data to a file.
+ *
+ * @param dataToDecode Base64-encoded data as a string
+ * @param filename Filename for saving decoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean decodeToFile(final String dataToDecode, final String filename)
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE);
+ bos.write(dataToDecode.getBytes(Base64.PREFERRED_ENCODING));
+ success = true;
+ } // end try
+ catch (java.io.IOException e)
+ {
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try
+ {
+ bos.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ return success;
+ } // end decodeToFile
+
+ /**
+ * Convenience method for reading a base64-encoded
+ * file and decoding it.
+ *
+ * @param filename Filename for reading encoded data
+ * @return decoded byte array or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static byte[] decodeFromFile(final String filename)
+ {
+ byte[] decodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File(filename);
+ byte[] buffer = null;
+ int length = 0;
+ int numBytes = 0;
+
+ // Check for size of file
+ if (file.length() > Integer.MAX_VALUE)
+ {
+ System.err.println("File is too big for this convenience method (" + file.length() + " bytes).");
+ return null;
+ } // end if: file too big for int index
+ buffer = new byte[(int)file.length()];
+
+ // Open a stream
+ bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.DECODE);
+
+ // Read until done
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ {
+ length += numBytes;
+ }
+
+ // Save in a variable to return
+ decodedData = new byte[length];
+ System.arraycopy(buffer, 0, decodedData, 0, length);
+
+ } // end try
+ catch (java.io.IOException e)
+ {
+ System.err.println("Error decoding from file " + filename);
+ } // end catch: IOException
+ finally
+ {
+ try
+ {
+ bis.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ return decodedData;
+ } // end decodeFromFile
+
+ /**
+ * Convenience method for reading a binary file
+ * and base64-encoding it.
+ *
+ * @param filename Filename for reading binary data
+ * @return base64-encoded string or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static String encodeFromFile(final String filename)
+ {
+ String encodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File(filename);
+ byte[] buffer = new byte[Math.max((int)(file.length() * 1.4), 40)]; // Need max() for math on small files
+ // (v2.2.1)
+ int length = 0;
+ int numBytes = 0;
+
+ // Open a stream
+ bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.ENCODE);
+
+ // Read until done
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ {
+ length += numBytes;
+ }
+
+ // Save in a variable to return
+ encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
+
+ } // end try
+ catch (java.io.IOException e)
+ {
+ System.err.println("Error encoding from file " + filename);
+ } // end catch: IOException
+ finally
+ {
+ try
+ {
+ bis.close();
+ }
+ catch (Exception e)
+ {
+ }
+ } // end finally
+
+ return encodedData;
+ } // end encodeFromFile
+
+ /**
+ * Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @return true if the operation is successful
+ * @since 2.2
+ */
+ public static boolean encodeFileToFile(final String infile, final String outfile)
+ {
+ boolean success = false;
+ java.io.InputStream in = null;
+ java.io.OutputStream out = null;
+ try
+ {
+ in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)),
+ Base64.ENCODE);
+ out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
+ byte[] buffer = new byte[65536]; // 64K
+ int read = -1;
+ while ((read = in.read(buffer)) >= 0)
+ {
+ out.write(buffer, 0, read);
+ } // end while: through file
+ success = true;
+ }
+ catch (java.io.IOException exc)
+ {
+ exc.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch (Exception exc)
+ {
+ }
+ try
+ {
+ out.close();
+ }
+ catch (Exception exc)
+ {
+ }
+ } // end finally
+
+ return success;
+ } // end encodeFileToFile
+
+ /**
+ * Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @return true if the operation is successful
+ * @since 2.2
+ */
+ public static boolean decodeFileToFile(final String infile, final String outfile)
+ {
+ boolean success = false;
+ java.io.InputStream in = null;
+ java.io.OutputStream out = null;
+ try
+ {
+ in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)),
+ Base64.DECODE);
+ out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
+ byte[] buffer = new byte[65536]; // 64K
+ int read = -1;
+ while ((read = in.read(buffer)) >= 0)
+ {
+ out.write(buffer, 0, read);
+ } // end while: through file
+ success = true;
+ }
+ catch (java.io.IOException exc)
+ {
+ exc.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch (Exception exc)
+ {
+ }
+ try
+ {
+ out.close();
+ }
+ catch (Exception exc)
+ {
+ }
+ } // end finally
+
+ return success;
+ } // end decodeFileToFile
+
+ /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
+
+ /**
+ * A {@link Base64.InputStream} will read data from another
+ * <tt>java.io.InputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class InputStream extends java.io.FilterInputStream
+ {
+ private final boolean encode; // Encoding or decoding
+
+ private int position; // Current position in the buffer
+
+ private final byte[] buffer; // Small buffer holding converted data
+
+ private final int bufferLength; // Length of buffer (3 or 4)
+
+ private int numSigBytes; // Number of meaningful bytes in the buffer
+
+ private int lineLength;
+
+ private final boolean breakLines; // Break lines at less than 80 characters
+
+ private final int options; // Record options used to create the stream.
+
+ private final byte[] alphabet; // Local copies to avoid extra method calls
+
+ private final byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.InputStream} in DECODE mode.
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @since 1.3
+ */
+ public InputStream(final java.io.InputStream in)
+ {
+ this(in, Base64.DECODE);
+ } // end constructor
+
+ /**
+ * Constructs a {@link Base64.InputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+ *
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @param options Specified options
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public InputStream(final java.io.InputStream in, final int options)
+ {
+ super(in);
+ breakLines = (options & Base64.DONT_BREAK_LINES) != Base64.DONT_BREAK_LINES;
+ encode = (options & Base64.ENCODE) == Base64.ENCODE;
+ bufferLength = encode ? 4 : 3;
+ buffer = new byte[bufferLength];
+ position = -1;
+ lineLength = 0;
+ this.options = options; // Record for later, mostly to determine which alphabet to use
+ alphabet = Base64.getAlphabet(options);
+ decodabet = Base64.getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Reads enough of the input stream to convert
+ * to/from Base64 and returns the next byte.
+ *
+ * @return next byte
+ * @since 1.3
+ */
+ @Override
+ public int read() throws java.io.IOException
+ {
+ // Do we need to get data?
+ if (position < 0)
+ {
+ if (encode)
+ {
+ byte[] b3 = new byte[3];
+ int numBinaryBytes = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ try
+ {
+ int b = in.read();
+
+ // If end of stream, b is -1.
+ if (b >= 0)
+ {
+ b3[i] = (byte)b;
+ numBinaryBytes++;
+ } // end if: not end of stream
+
+ } // end try: read
+ catch (java.io.IOException e)
+ {
+ // Only a problem if we got no data at all.
+ if (i == 0)
+ {
+ throw e;
+ }
+
+ } // end catch
+ } // end for: each needed input byte
+
+ if (numBinaryBytes > 0)
+ {
+ Base64.encode3to4(b3, 0, numBinaryBytes, buffer, 0, options);
+ position = 0;
+ numSigBytes = 4;
+ } // end if: got data
+ else
+ {
+ return -1;
+ }
+ } // end if: encoding
+
+ // Else decoding
+ else
+ {
+ byte[] b4 = new byte[4];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ {
+ // Read four "meaningful" bytes:
+ int b = 0;
+ do
+ {
+ b = in.read();
+ }
+ while (b >= 0 && decodabet[b & 0x7f] <= Base64.WHITE_SPACE_ENC);
+
+ if (b < 0)
+ {
+ break; // Reads a -1 if end of stream
+ }
+
+ b4[i] = (byte)b;
+ } // end for: each needed input byte
+
+ if (i == 4)
+ {
+ numSigBytes = Base64.decode4to3(b4, 0, buffer, 0, options);
+ position = 0;
+ } // end if: got four characters
+ else if (i == 0)
+ {
+ return -1;
+ }
+ else
+ {
+ // Must have broken out from above.
+ throw new java.io.IOException("Improperly padded Base64 input.");
+ }
+
+ } // end else: decode
+ } // end else: get data
+
+ // Got data?
+ if (position >= 0)
+ {
+ // End of relevant data?
+ if ( /*!encode &&*/position >= numSigBytes)
+ {
+ return -1;
+ }
+
+ if (encode && breakLines && lineLength >= Base64.MAX_LINE_LENGTH)
+ {
+ lineLength = 0;
+ return '\n';
+ } // end if
+ else
+ {
+ lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
+
+ int b = buffer[position++];
+
+ if (position >= bufferLength)
+ {
+ position = -1;
+ }
+
+ return b & 0xFF; // This is how you "cast" a byte that's
+ // intended to be unsigned.
+ } // end else
+ } // end if: position >= 0
+ else
+ {
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new java.io.IOException("Error in Base64 code reading stream.");
+ }
+ } // end read
+
+ /**
+ * Calls {@link #read()} repeatedly until the end of stream
+ * is reached or <var>len</var> bytes are read.
+ * Returns number of bytes read into array or -1 if
+ * end of stream is encountered.
+ *
+ * @param dest array to hold values
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @return bytes read into array or -1 if end of stream is encountered.
+ * @since 1.3
+ */
+ @Override
+ public int read(final byte[] dest, final int off, final int len) throws java.io.IOException
+ {
+ int i;
+ int b;
+ for (i = 0; i < len; i++)
+ {
+ b = read();
+
+ // if( b < 0 && i == 0 )
+ // return -1;
+
+ if (b >= 0)
+ {
+ dest[off + i] = (byte)b;
+ }
+ else if (i == 0)
+ {
+ return -1;
+ }
+ else
+ {
+ break; // Out of 'for' loop
+ }
+ } // end for: each byte read
+ return i;
+ } // end read
+
+ } // end inner class InputStream
+
+ /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
+
+ /**
+ * A {@link Base64.OutputStream} will write data to another
+ * <tt>java.io.OutputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class OutputStream extends java.io.FilterOutputStream
+ {
+ private final boolean encode;
+
+ private int position;
+
+ private byte[] buffer;
+
+ private final int bufferLength;
+
+ private int lineLength;
+
+ private final boolean breakLines;
+
+ private final byte[] b4; // Scratch used in a few places
+
+ private boolean suspendEncoding;
+
+ private final int options; // Record for later
+
+ private final byte[] alphabet; // Local copies to avoid extra method calls
+
+ private final byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in ENCODE mode.
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @since 1.3
+ */
+ public OutputStream(final java.io.OutputStream out)
+ {
+ this(out, Base64.ENCODE);
+ } // end constructor
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @param options Specified options.
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 1.3
+ */
+ public OutputStream(final java.io.OutputStream out, final int options)
+ {
+ super(out);
+ breakLines = (options & Base64.DONT_BREAK_LINES) != Base64.DONT_BREAK_LINES;
+ encode = (options & Base64.ENCODE) == Base64.ENCODE;
+ bufferLength = encode ? 3 : 4;
+ buffer = new byte[bufferLength];
+ position = 0;
+ lineLength = 0;
+ suspendEncoding = false;
+ b4 = new byte[4];
+ this.options = options;
+ alphabet = Base64.getAlphabet(options);
+ decodabet = Base64.getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Writes the byte to the output stream after
+ * converting to/from Base64 notation.
+ * When encoding, bytes are buffered three
+ * at a time before the output stream actually
+ * gets a write() call.
+ * When decoding, bytes are buffered four
+ * at a time.
+ *
+ * @param theByte the byte to write
+ * @since 1.3
+ */
+ @Override
+ public void write(final int theByte) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if (suspendEncoding)
+ {
+ super.out.write(theByte);
+ return;
+ } // end if: supsended
+
+ // Encode?
+ if (encode)
+ {
+ buffer[position++] = (byte)theByte;
+ if (position >= bufferLength) // Enough to encode.
+ {
+ out.write(Base64.encode3to4(b4, buffer, bufferLength, options));
+
+ lineLength += 4;
+ if (breakLines && lineLength >= Base64.MAX_LINE_LENGTH)
+ {
+ out.write(Base64.NEW_LINE);
+ lineLength = 0;
+ } // end if: end of line
+
+ position = 0;
+ } // end if: enough to output
+ } // end if: encoding
+
+ // Else, Decoding
+ else
+ {
+ // Meaningful Base64 character?
+ if (decodabet[theByte & 0x7f] > Base64.WHITE_SPACE_ENC)
+ {
+ buffer[position++] = (byte)theByte;
+ if (position >= bufferLength) // Enough to output.
+ {
+ int len = Base64.decode4to3(buffer, 0, b4, 0, options);
+ out.write(b4, 0, len);
+ // out.write( Base64.decode4to3( buffer ) );
+ position = 0;
+ } // end if: enough to output
+ } // end if: meaningful base64 character
+ else if (decodabet[theByte & 0x7f] != Base64.WHITE_SPACE_ENC)
+ {
+ throw new java.io.IOException("Invalid character in Base64 data.");
+ }
+ } // end else: decoding
+ } // end write
+
+ /**
+ * Calls {@link #write(int)} repeatedly until <var>len</var>
+ * bytes are written.
+ *
+ * @param theBytes array from which to read bytes
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @since 1.3
+ */
+ @Override
+ public void write(final byte[] theBytes, final int off, final int len) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if (suspendEncoding)
+ {
+ super.out.write(theBytes, off, len);
+ return;
+ } // end if: supsended
+
+ for (int i = 0; i < len; i++)
+ {
+ write(theBytes[off + i]);
+ } // end for: each byte written
+
+ } // end write
+
+ /**
+ * Method added by PHIL. [Thanks, PHIL. -Rob]
+ * This pads the buffer without closing the stream.
+ */
+ public void flushBase64() throws java.io.IOException
+ {
+ if (position > 0)
+ {
+ if (encode)
+ {
+ out.write(Base64.encode3to4(b4, buffer, position, options));
+ position = 0;
+ } // end if: encoding
+ else
+ {
+ throw new java.io.IOException("Base64 input not properly padded.");
+ }
+ } // end if: buffer partially full
+
+ } // end flush
+
+ /**
+ * Flushes and closes (I think, in the superclass) the stream.
+ *
+ * @since 1.3
+ */
+ @Override
+ public void close() throws java.io.IOException
+ {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
+
+ buffer = null;
+ out = null;
+ } // end close
+
+ /**
+ * Suspends encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void suspendEncoding() throws java.io.IOException
+ {
+ flushBase64();
+ suspendEncoding = true;
+ } // end suspendEncoding
+
+ /**
+ * Resumes encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void resumeEncoding()
+ {
+ suspendEncoding = false;
+ } // end resumeEncoding
+
+ } // end inner class OutputStream
+
+} // end class Base64
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentHashSet.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentHashSet.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentHashSet.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentHashSet.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ *
+ * A ConcurrentHashSet.
+ *
+ * Offers same concurrency as ConcurrentHashMap but for a Set
+ *
+ * @author <a href="tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1935 $</tt>
+ *
+ * $Id: ConcurrentReaderHashSet.java 1935 2007-01-09 23:29:20Z clebert.suconic at jboss.com $
+ */
+public class ConcurrentHashSet<E> extends AbstractSet<E> implements ConcurrentSet<E>
+{
+ private final ConcurrentMap<E, Object> theMap;
+
+ private static final Object dummy = new Object();
+
+ public ConcurrentHashSet()
+ {
+ theMap = new ConcurrentHashMap<E, Object>();
+ }
+
+ @Override
+ public int size()
+ {
+ return theMap.size();
+ }
+
+ @Override
+ public Iterator<E> iterator()
+ {
+ return theMap.keySet().iterator();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return theMap.isEmpty();
+ }
+
+ @Override
+ public boolean add(final E o)
+ {
+ return theMap.put(o, ConcurrentHashSet.dummy) == null;
+ }
+
+ @Override
+ public boolean contains(final Object o)
+ {
+ return theMap.containsKey(o);
+ }
+
+ @Override
+ public void clear()
+ {
+ theMap.clear();
+ }
+
+ @Override
+ public boolean remove(final Object o)
+ {
+ return theMap.remove(o) == ConcurrentHashSet.dummy;
+ }
+
+ public boolean addIfAbsent(final E o)
+ {
+ Object obj = theMap.putIfAbsent(o, ConcurrentHashSet.dummy);
+
+ return obj == null;
+ }
+
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentSet.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentSet.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentSet.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/ConcurrentSet.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.util.Set;
+
+/**
+ *
+ * A ConcurrentSet
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ * @param <E>
+ */
+public interface ConcurrentSet<E> extends Set<E>
+{
+ boolean addIfAbsent(E o);
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/HornetQThreadFactory.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/HornetQThreadFactory.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/HornetQThreadFactory.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/HornetQThreadFactory.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.hornetq.utils;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.hornetq.core.logging.Logger;
+
+/**
+ *
+ * A HornetQThreadFactory
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class HornetQThreadFactory implements ThreadFactory
+{
+ private static final Logger log = Logger.getLogger(HornetQThreadFactory.class);
+
+ private final ThreadGroup group;
+
+ private final AtomicInteger threadCount = new AtomicInteger(0);
+
+ private final int threadPriority;
+
+ private final boolean daemon;
+
+ private final ClassLoader tccl;
+
+ public HornetQThreadFactory(final String groupName, final boolean daemon, final ClassLoader tccl)
+ {
+ this(groupName, Thread.NORM_PRIORITY, daemon, tccl);
+ }
+
+ public HornetQThreadFactory(final String groupName, final int threadPriority, final boolean daemon, final ClassLoader tccl)
+ {
+ group = new ThreadGroup(groupName + "-" + System.identityHashCode(this));
+
+ this.threadPriority = threadPriority;
+
+ this.tccl = tccl;
+
+ this.daemon = daemon;
+ }
+
+ public Thread newThread(final Runnable command)
+ {
+ final Thread t;
+ // attach the thread to a group only if there is no security manager:
+ // when sandboxed, the code does not have the RuntimePermission modifyThreadGroup
+ if (System.getSecurityManager() == null)
+ {
+ t = new Thread(group, command, "Thread-" + threadCount.getAndIncrement() + " (group:" + group.getName() + ")");
+ }
+ else
+ {
+ t = new Thread(command, "Thread-" + threadCount.getAndIncrement());
+ }
+
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ t.setDaemon(daemon);
+ t.setPriority(threadPriority);
+ return null;
+ }
+ });
+
+ try
+ {
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ t.setContextClassLoader(tccl);
+ return null;
+ }
+ });
+ }
+ catch (java.security.AccessControlException e)
+ {
+ log.warn("Missing privileges to set Thread Context Class Loader on Thread Factory. Using current Thread Context Class Loader");
+ }
+
+ return t;
+ }
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/ReusableLatch.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/ReusableLatch.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/ReusableLatch.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/ReusableLatch.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+/**
+ *
+ * <p>This class will use the framework provided to by AbstractQueuedSynchronizer.</p>
+ * <p>AbstractQueuedSynchronizer is the framework for any sort of concurrent synchronization, such as Semaphores, events, etc, based on AtomicIntegers.</p>
+ *
+ * <p>This class works just like CountDownLatch, with the difference you can also increase the counter</p>
+ *
+ * <p>It could be used for sync points when one process is feeding the latch while another will wait when everything is done. (e.g. waiting IO completions to finish)</p>
+ *
+ * <p>On HornetQ we have the requirement of increment and decrement a counter until the user fires a ready event (commit). At that point we just act as a regular countDown.</p>
+ *
+ * <p>Note: This latch is reusable. Once it reaches zero, you can call up again, and reuse it on further waits.</p>
+ *
+ * <p>For example: prepareTransaction will wait for the current completions, and further adds will be called on the latch. Later on when commit is called you can reuse the same latch.</p>
+ *
+ * @author Clebert Suconic
+ * */
+public class ReusableLatch
+{
+ /**
+ * Look at the doc and examples provided by AbstractQueuedSynchronizer for more information
+ * @see AbstractQueuedSynchronizer*/
+ @SuppressWarnings("serial")
+ private static class CountSync extends AbstractQueuedSynchronizer
+ {
+ public CountSync(int count)
+ {
+ setState(count);
+ }
+
+ public int getCount()
+ {
+ return getState();
+ }
+
+ public void setCount(final int count)
+ {
+ setState(count);
+ }
+
+ @Override
+ public int tryAcquireShared(final int numberOfAqcquires)
+ {
+ return getState() == 0 ? 1 : -1;
+ }
+
+ public void add()
+ {
+ for (;;)
+ {
+ int actualState = getState();
+ int newState = actualState + 1;
+ if (compareAndSetState(actualState, newState))
+ {
+ return;
+ }
+ }
+ }
+
+ @Override
+ public boolean tryReleaseShared(final int numberOfReleases)
+ {
+ for (;;)
+ {
+ int actualState = getState();
+ if (actualState == 0)
+ {
+ return true;
+ }
+
+ int newState = actualState - numberOfReleases;
+
+ if (newState < 0)
+ {
+ newState = 0;
+ }
+
+ if (compareAndSetState(actualState, newState))
+ {
+ return newState == 0;
+ }
+ }
+ }
+ }
+
+ private final CountSync control;
+
+ public ReusableLatch()
+ {
+ this(0);
+ }
+
+ public ReusableLatch(final int count)
+ {
+ control = new CountSync(count);
+ }
+
+ public int getCount()
+ {
+ return control.getCount();
+ }
+
+ public void setCount(final int count)
+ {
+ control.setCount(count);
+ }
+
+ public void countUp()
+ {
+ control.add();
+ }
+
+ public void countDown()
+ {
+ control.releaseShared(1);
+ }
+
+
+ public void countDown(final int count)
+ {
+ control.releaseShared(count);
+ }
+
+ public void await() throws InterruptedException
+ {
+ control.acquireSharedInterruptibly(1);
+ }
+
+ public boolean await(final long milliseconds) throws InterruptedException
+ {
+ return control.tryAcquireSharedNanos(1, TimeUnit.MILLISECONDS.toNanos(milliseconds));
+ }
+
+ public boolean await(final long timeWait, TimeUnit timeUnit) throws InterruptedException
+ {
+ return control.tryAcquireSharedNanos(1, timeUnit.toNanos(timeWait));
+ }
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/TypedProperties.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/TypedProperties.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/TypedProperties.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/TypedProperties.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,1060 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import static org.hornetq.utils.DataConstants.BOOLEAN;
+import static org.hornetq.utils.DataConstants.BYTE;
+import static org.hornetq.utils.DataConstants.BYTES;
+import static org.hornetq.utils.DataConstants.CHAR;
+import static org.hornetq.utils.DataConstants.DOUBLE;
+import static org.hornetq.utils.DataConstants.FLOAT;
+import static org.hornetq.utils.DataConstants.INT;
+import static org.hornetq.utils.DataConstants.LONG;
+import static org.hornetq.utils.DataConstants.NULL;
+import static org.hornetq.utils.DataConstants.SHORT;
+import static org.hornetq.utils.DataConstants.STRING;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.api.core.PropertyConversionException;
+import org.hornetq.api.core.SimpleString;
+import org.hornetq.core.logging.Logger;
+
+/**
+ *
+ * Property Value Conversion.
+ * <p>
+ * This implementation follows section 3.5.4 of the <i>Java Message Service<i>
+ * specification (Version 1.1 April 12, 2002).
+ * <p>
+ * TODO - should have typed property getters and do conversions herein
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
+ * @see <i>Java Message Service<i> specification (Version 1.1 April 12, 2002), section 3.5.4.
+ */
+public class TypedProperties
+{
+ private static final Logger log = Logger.getLogger(TypedProperties.class);
+
+ private static final SimpleString HQ_PROPNAME = new SimpleString("_HQ_");
+
+ private Map<SimpleString, PropertyValue> properties;
+
+ private volatile int size;
+
+ private boolean internalProperties;
+
+ public TypedProperties()
+ {
+ }
+
+ public int getMemoryOffset()
+ {
+ // The estimate is basically the encode size + 2 object references for each entry in the map
+ // Note we don't include the attributes or anything else since they already included in the memory estimate
+ // of the ServerMessage
+
+ return properties == null ? 0 : size + 2 * DataConstants.SIZE_INT * properties.size();
+ }
+
+ public TypedProperties(final TypedProperties other)
+ {
+ properties = other.properties == null ? null : new HashMap<SimpleString, PropertyValue>(other.properties);
+ size = other.size;
+ }
+
+ public boolean hasInternalProperties()
+ {
+ return internalProperties;
+ }
+
+ public void putBooleanProperty(final SimpleString key, final boolean value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new BooleanValue(value));
+ }
+
+ public void putByteProperty(final SimpleString key, final byte value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new ByteValue(value));
+ }
+
+ public void putBytesProperty(final SimpleString key, final byte[] value)
+ {
+ checkCreateProperties();
+ doPutValue(key, value == null ? new NullValue() : new BytesValue(value));
+ }
+
+ public void putShortProperty(final SimpleString key, final short value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new ShortValue(value));
+ }
+
+ public void putIntProperty(final SimpleString key, final int value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new IntValue(value));
+ }
+
+ public void putLongProperty(final SimpleString key, final long value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new LongValue(value));
+ }
+
+ public void putFloatProperty(final SimpleString key, final float value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new FloatValue(value));
+ }
+
+ public void putDoubleProperty(final SimpleString key, final double value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new DoubleValue(value));
+ }
+
+ public void putSimpleStringProperty(final SimpleString key, final SimpleString value)
+ {
+ checkCreateProperties();
+ doPutValue(key, value == null ? new NullValue() : new StringValue(value));
+ }
+
+ public void putCharProperty(final SimpleString key, final char value)
+ {
+ checkCreateProperties();
+ doPutValue(key, new CharValue(value));
+ }
+
+ public void putTypedProperties(final TypedProperties otherProps)
+ {
+ if (otherProps == null || otherProps.properties == null)
+ {
+ return;
+ }
+
+ checkCreateProperties();
+ Set<Entry<SimpleString, PropertyValue>> otherEntries = otherProps.properties.entrySet();
+ for (Entry<SimpleString, PropertyValue> otherEntry : otherEntries)
+ {
+ doPutValue(otherEntry.getKey(), otherEntry.getValue());
+ }
+ }
+
+ public Object getProperty(final SimpleString key)
+ {
+ return doGetProperty(key);
+ }
+
+ public Boolean getBooleanProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Boolean.valueOf(null);
+ }
+ else if (value instanceof Boolean)
+ {
+ return (Boolean)value;
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Boolean.valueOf(((SimpleString)value).toString()).booleanValue();
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Byte getByteProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Byte.valueOf(null);
+ }
+ else if (value instanceof Byte)
+ {
+ return (Byte)value;
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Byte.parseByte(((SimpleString)value).toString());
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Character getCharProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ throw new NullPointerException("Invalid conversion");
+ }
+
+ if (value instanceof Character)
+ {
+ return ((Character)value).charValue();
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public byte[] getBytesProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return null;
+ }
+ else if (value instanceof byte[])
+ {
+ return (byte[])value;
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Double getDoubleProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Double.valueOf(null);
+ }
+ else if (value instanceof Float)
+ {
+ return ((Float)value).doubleValue();
+ }
+ else if (value instanceof Double)
+ {
+ return (Double)value;
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Double.parseDouble(((SimpleString)value).toString());
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Integer getIntProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Integer.valueOf(null);
+ }
+ else if (value instanceof Integer)
+ {
+ return (Integer)value;
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte)value).intValue();
+ }
+ else if (value instanceof Short)
+ {
+ return ((Short)value).intValue();
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Integer.parseInt(((SimpleString)value).toString());
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Long getLongProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Long.valueOf(null);
+ }
+ else if (value instanceof Long)
+ {
+ return (Long)value;
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte)value).longValue();
+ }
+ else if (value instanceof Short)
+ {
+ return ((Short)value).longValue();
+ }
+ else if (value instanceof Integer)
+ {
+ return ((Integer)value).longValue();
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Long.parseLong(((SimpleString)value).toString());
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid conversion");
+ }
+ }
+
+ public Short getShortProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ {
+ return Short.valueOf(null);
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte)value).shortValue();
+ }
+ else if (value instanceof Short)
+ {
+ return (Short)value;
+ }
+ else if (value instanceof SimpleString)
+ {
+ return Short.parseShort(((SimpleString)value).toString());
+ }
+ else
+ {
+ throw new PropertyConversionException("Invalid Conversion.");
+ }
+ }
+
+ public Float getFloatProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+ if (value == null)
+ return Float.valueOf(null);
+ if (value instanceof Float)
+ {
+ return ((Float)value).floatValue();
+ }
+ if (value instanceof SimpleString)
+ {
+ return Float.parseFloat(((SimpleString)value).toString());
+ }
+ throw new PropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public SimpleString getSimpleStringProperty(final SimpleString key) throws PropertyConversionException
+ {
+ Object value = doGetProperty(key);
+
+ if (value == null)
+ {
+ return null;
+ }
+
+ if (value instanceof SimpleString)
+ {
+ return (SimpleString)value;
+ }
+ else if (value instanceof Boolean)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Character)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Byte)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Short)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Integer)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Long)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Float)
+ {
+ return new SimpleString(value.toString());
+ }
+ else if (value instanceof Double)
+ {
+ return new SimpleString(value.toString());
+ }
+ throw new PropertyConversionException("Invalid conversion");
+ }
+
+ public Object removeProperty(final SimpleString key)
+ {
+ return doRemoveProperty(key);
+ }
+
+ public boolean containsProperty(final SimpleString key)
+ {
+ if (size == 0)
+ {
+ return false;
+
+ }
+ else
+ {
+ return properties.containsKey(key);
+ }
+ }
+
+ public Set<SimpleString> getPropertyNames()
+ {
+ if (size == 0)
+ {
+ return Collections.emptySet();
+ }
+ else
+ {
+ return properties.keySet();
+ }
+ }
+
+ public synchronized void decode(final HornetQBuffer buffer)
+ {
+ byte b = buffer.readByte();
+
+ if (b == DataConstants.NULL)
+ {
+ properties = null;
+ }
+ else
+ {
+ int numHeaders = buffer.readInt();
+
+ properties = new HashMap<SimpleString, PropertyValue>(numHeaders);
+ size = 0;
+
+ for (int i = 0; i < numHeaders; i++)
+ {
+ int len = buffer.readInt();
+ byte[] data = new byte[len];
+ buffer.readBytes(data);
+ SimpleString key = new SimpleString(data);
+
+ byte type = buffer.readByte();
+
+ PropertyValue val;
+
+ switch (type)
+ {
+ case NULL:
+ {
+ val = new NullValue();
+ doPutValue(key, val);
+ break;
+ }
+ case CHAR:
+ {
+ val = new CharValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BOOLEAN:
+ {
+ val = new BooleanValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BYTE:
+ {
+ val = new ByteValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BYTES:
+ {
+ val = new BytesValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case SHORT:
+ {
+ val = new ShortValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case INT:
+ {
+ val = new IntValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case LONG:
+ {
+ val = new LongValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case FLOAT:
+ {
+ val = new FloatValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case DOUBLE:
+ {
+ val = new DoubleValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case STRING:
+ {
+ val = new StringValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ default:
+ {
+ throw new IllegalArgumentException("Invalid type: " + type);
+ }
+ }
+ }
+ }
+ }
+
+ public synchronized void encode(final HornetQBuffer buffer)
+ {
+ if (properties == null)
+ {
+ buffer.writeByte(DataConstants.NULL);
+ }
+ else
+ {
+ buffer.writeByte(DataConstants.NOT_NULL);
+
+ buffer.writeInt(properties.size());
+
+ for (Map.Entry<SimpleString, PropertyValue> entry : properties.entrySet())
+ {
+ SimpleString s = entry.getKey();
+ byte[] data = s.getData();
+ buffer.writeInt(data.length);
+ buffer.writeBytes(data);
+
+ entry.getValue().write(buffer);
+ }
+ }
+ }
+
+ public int getEncodeSize()
+ {
+ if (properties == null)
+ {
+ return DataConstants.SIZE_BYTE;
+ }
+ else
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size;
+ }
+ }
+
+ public void clear()
+ {
+ if (properties != null)
+ {
+ properties.clear();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "TypedProperties[" + properties + "]";
+ }
+
+ // Private ------------------------------------------------------------------------------------
+
+ private void checkCreateProperties()
+ {
+ if (properties == null)
+ {
+ properties = new HashMap<SimpleString, PropertyValue>();
+ }
+ }
+
+ private synchronized void doPutValue(final SimpleString key, final PropertyValue value)
+ {
+ if (key.startsWith(HQ_PROPNAME))
+ {
+ internalProperties = true;
+ }
+
+ PropertyValue oldValue = properties.put(key, value);
+ if (oldValue != null)
+ {
+ size += value.encodeSize() - oldValue.encodeSize();
+ }
+ else
+ {
+ size += SimpleString.sizeofString(key) + value.encodeSize();
+ }
+ }
+
+ private synchronized Object doRemoveProperty(final SimpleString key)
+ {
+ if (properties == null)
+ {
+ return null;
+ }
+
+ PropertyValue val = properties.remove(key);
+
+ if (val == null)
+ {
+ return null;
+ }
+ else
+ {
+ size -= SimpleString.sizeofString(key) + val.encodeSize();
+
+ return val.getValue();
+ }
+ }
+
+ private synchronized Object doGetProperty(final Object key)
+ {
+ if (size == 0)
+ {
+ return null;
+ }
+
+ PropertyValue val = properties.get(key);
+
+ if (val == null)
+ {
+ return null;
+ }
+ else
+ {
+ return val.getValue();
+ }
+ }
+
+ // Inner classes ------------------------------------------------------------------------------
+
+ private static abstract class PropertyValue
+ {
+ abstract Object getValue();
+
+ abstract void write(HornetQBuffer buffer);
+
+ abstract int encodeSize();
+
+ @Override
+ public String toString()
+ {
+ return "" + getValue();
+ }
+ }
+
+ private static final class NullValue extends PropertyValue
+ {
+ public NullValue()
+ {
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return null;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.NULL);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE;
+ }
+
+ }
+
+ private static final class BooleanValue extends PropertyValue
+ {
+ final boolean val;
+
+ public BooleanValue(final boolean val)
+ {
+ this.val = val;
+ }
+
+ public BooleanValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readBoolean();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.BOOLEAN);
+ buffer.writeBoolean(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN;
+ }
+
+ }
+
+ private static final class ByteValue extends PropertyValue
+ {
+ final byte val;
+
+ public ByteValue(final byte val)
+ {
+ this.val = val;
+ }
+
+ public ByteValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readByte();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.BYTE);
+ buffer.writeByte(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_BYTE;
+ }
+ }
+
+ private static final class BytesValue extends PropertyValue
+ {
+ final byte[] val;
+
+ public BytesValue(final byte[] val)
+ {
+ this.val = val;
+ }
+
+ public BytesValue(final HornetQBuffer buffer)
+ {
+ int len = buffer.readInt();
+ val = new byte[len];
+ buffer.readBytes(val);
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.BYTES);
+ buffer.writeInt(val.length);
+ buffer.writeBytes(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + val.length;
+ }
+
+ }
+
+ private static final class ShortValue extends PropertyValue
+ {
+ final short val;
+
+ public ShortValue(final short val)
+ {
+ this.val = val;
+ }
+
+ public ShortValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readShort();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.SHORT);
+ buffer.writeShort(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_SHORT;
+ }
+ }
+
+ private static final class IntValue extends PropertyValue
+ {
+ final int val;
+
+ public IntValue(final int val)
+ {
+ this.val = val;
+ }
+
+ public IntValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readInt();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.INT);
+ buffer.writeInt(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
+ }
+ }
+
+ private static final class LongValue extends PropertyValue
+ {
+ final long val;
+
+ public LongValue(final long val)
+ {
+ this.val = val;
+ }
+
+ public LongValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readLong();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.LONG);
+ buffer.writeLong(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
+ }
+ }
+
+ private static final class FloatValue extends PropertyValue
+ {
+ final float val;
+
+ public FloatValue(final float val)
+ {
+ this.val = val;
+ }
+
+ public FloatValue(final HornetQBuffer buffer)
+ {
+ val = Float.intBitsToFloat(buffer.readInt());
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.FLOAT);
+ buffer.writeInt(Float.floatToIntBits(val));
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_FLOAT;
+ }
+
+ }
+
+ private static final class DoubleValue extends PropertyValue
+ {
+ final double val;
+
+ public DoubleValue(final double val)
+ {
+ this.val = val;
+ }
+
+ public DoubleValue(final HornetQBuffer buffer)
+ {
+ val = Double.longBitsToDouble(buffer.readLong());
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.DOUBLE);
+ buffer.writeLong(Double.doubleToLongBits(val));
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_DOUBLE;
+ }
+ }
+
+ private static final class CharValue extends PropertyValue
+ {
+ final char val;
+
+ public CharValue(final char val)
+ {
+ this.val = val;
+ }
+
+ public CharValue(final HornetQBuffer buffer)
+ {
+ val = (char)buffer.readShort();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.CHAR);
+ buffer.writeShort((short)val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_CHAR;
+ }
+ }
+
+ private static final class StringValue extends PropertyValue
+ {
+ final SimpleString val;
+
+ public StringValue(final SimpleString val)
+ {
+ this.val = val;
+ }
+
+ public StringValue(final HornetQBuffer buffer)
+ {
+ val = buffer.readSimpleString();
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return val;
+ }
+
+ @Override
+ public void write(final HornetQBuffer buffer)
+ {
+ buffer.writeByte(DataConstants.STRING);
+ buffer.writeSimpleString(val);
+ }
+
+ @Override
+ public int encodeSize()
+ {
+ return DataConstants.SIZE_BYTE + SimpleString.sizeofString(val);
+ }
+ }
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUID.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/UUID.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUID.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUID.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,236 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
+ *
+ * Licensed under the License specified in the file licenses/LICENSE.txt which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+/**
+ * UUID represents Universally Unique Identifiers (aka Global UID in Windows
+ * world). UUIDs are usually generated via UUIDGenerator (or in case of 'Null
+ * UUID', 16 zero bytes, via static method getNullUUID()), or received from
+ * external systems.
+ *
+ * By default class caches the string presentations of UUIDs so that description
+ * is only created the first time it's needed. For memory stingy applications
+ * this caching can be turned off (note though that if uuid.toString() is never
+ * called, desc is never calculated so only loss is the space allocated for the
+ * desc pointer... which can of course be commented out to save memory).
+ *
+ * Similarly, hash code is calculated when it's needed for the first time, and
+ * from thereon that value is just returned. This means that using UUIDs as keys
+ * should be reasonably efficient.
+ *
+ * UUIDs can be compared for equality, serialized, cloned and even sorted.
+ * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by
+ * first ordering based on type (in the order of numeric values of types),
+ * secondarily by time stamp (only for time-based time stamps), and finally by
+ * straight numeric byte-by-byte comparison (from most to least significant
+ * bytes).
+ */
+
+public final class UUID
+{
+ private final static String kHexChars = "0123456789abcdefABCDEF";
+
+ public final static byte INDEX_CLOCK_HI = 6;
+
+ public final static byte INDEX_CLOCK_MID = 4;
+
+ public final static byte INDEX_CLOCK_LO = 0;
+
+ public final static byte INDEX_TYPE = 6;
+
+ // Clock seq. & variant are multiplexed...
+ public final static byte INDEX_CLOCK_SEQUENCE = 8;
+
+ public final static byte INDEX_VARIATION = 8;
+
+ public final static byte TYPE_NULL = 0;
+
+ public final static byte TYPE_TIME_BASED = 1;
+
+ public final static byte TYPE_DCE = 2; // Not used
+
+ public final static byte TYPE_NAME_BASED = 3;
+
+ public final static byte TYPE_RANDOM_BASED = 4;
+
+ /*
+ * 'Standard' namespaces defined (suggested) by UUID specs:
+ */
+ public final static String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
+
+ public final static String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
+
+ public final static String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
+
+ public final static String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
+
+ /*
+ * By default let's cache desc, can be turned off. For hash code there's no
+ * point in turning it off (since the int is already part of the instance
+ * memory allocation); if you want to save those 4 bytes (or possibly bit
+ * more if alignment is bad) just comment out hash caching.
+ */
+ private static boolean sDescCaching = true;
+
+ private final byte[] mId;
+
+ // Both string presentation and hash value may be cached...
+ private transient String mDesc = null;
+
+ private transient int mHashCode = 0;
+
+ /**
+ *
+ *
+ * @param type
+ * UUID type
+ * @param data
+ * 16 byte UUID contents
+ */
+ public UUID(final int type, final byte[] data)
+ {
+ mId = data;
+ // Type is multiplexed with time_hi:
+ mId[UUID.INDEX_TYPE] &= (byte)0x0F;
+ mId[UUID.INDEX_TYPE] |= (byte)(type << 4);
+ // Variant masks first two bits of the clock_seq_hi:
+ mId[UUID.INDEX_VARIATION] &= (byte)0x3F;
+ mId[UUID.INDEX_VARIATION] |= (byte)0x80;
+ }
+
+ public final byte[] asBytes()
+ {
+ return mId;
+ }
+
+ /**
+ * Could use just the default hash code, but we can probably create a better
+ * identity hash (ie. same contents generate same hash) manually, without
+ * sacrificing speed too much. Although multiplications with modulos would
+ * generate better hashing, let's use just shifts, and do 2 bytes at a time.
+ * <p>
+ * Of course, assuming UUIDs are randomized enough, even simpler approach
+ * might be good enough?
+ * <p>
+ * Is this a good hash? ... one of these days I better read more about basic
+ * hashing techniques I swear!
+ */
+ private final static int[] kShifts = { 3, 7, 17, 21, 29, 4, 9 };
+
+ @Override
+ public final int hashCode()
+ {
+ if (mHashCode == 0)
+ {
+ // Let's handle first and last byte separately:
+ int result = mId[0] & 0xFF;
+
+ result |= result << 16;
+ result |= result << 8;
+
+ for (int i = 1; i < 15; i += 2)
+ {
+ int curr = (mId[i] & 0xFF) << 8 | mId[i + 1] & 0xFF;
+ int shift = UUID.kShifts[i >> 1];
+
+ if (shift > 16)
+ {
+ result ^= curr << shift | curr >>> 32 - shift;
+ }
+ else
+ {
+ result ^= curr << shift;
+ }
+ }
+
+ // and then the last byte:
+ int last = mId[15] & 0xFF;
+ result ^= last << 3;
+ result ^= last << 13;
+
+ result ^= last << 27;
+ // Let's not accept hash 0 as it indicates 'not hashed yet':
+ if (result == 0)
+ {
+ mHashCode = -1;
+ }
+ else
+ {
+ mHashCode = result;
+ }
+ }
+ return mHashCode;
+ }
+
+ @Override
+ public final String toString()
+ {
+ /*
+ * Could be synchronized, but there isn't much harm in just taking our
+ * chances (ie. in the worst case we'll form the string more than once...
+ * but result is the same)
+ */
+
+ if (mDesc == null)
+ {
+ StringBuffer b = new StringBuffer(36);
+
+ for (int i = 0; i < 16; ++i)
+ {
+ // Need to bypass hyphens:
+ switch (i)
+ {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ b.append('-');
+ }
+ int hex = mId[i] & 0xFF;
+ b.append(UUID.kHexChars.charAt(hex >> 4));
+ b.append(UUID.kHexChars.charAt(hex & 0x0f));
+ }
+ if (!UUID.sDescCaching)
+ {
+ return b.toString();
+ }
+ mDesc = b.toString();
+ }
+ return mDesc;
+ }
+
+ /**
+ * Checking equality of UUIDs is easy; just compare the 128-bit number.
+ */
+ @Override
+ public final boolean equals(final Object o)
+ {
+ if (!(o instanceof UUID))
+ {
+ return false;
+ }
+ byte[] otherId = ((UUID)o).mId;
+ byte[] thisId = mId;
+ for (int i = 0; i < 16; ++i)
+ {
+ if (otherId[i] != thisId[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDGenerator.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDGenerator.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDGenerator.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDGenerator.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,293 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
+ *
+ * Licensed under the License specified in the file licenses/LICENSE.txt which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.lang.reflect.Method;
+import java.net.NetworkInterface;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Random;
+
+import org.hornetq.api.core.SimpleString;
+import org.hornetq.core.logging.Logger;
+
+public final class UUIDGenerator
+{
+ private final static UUIDGenerator sSingleton = new UUIDGenerator();
+
+ private static final Logger log = Logger.getLogger(UUIDGenerator.class);
+
+ // Windows has some fake adapters that will return the same HARDWARE ADDRESS on any computer. We need to ignore those
+ private static final byte[][] BLACK_LIST = new byte[][] { { 2, 0, 84, 85, 78, 1 } };
+
+ /**
+ * Random-generator, used by various UUID-generation methods:
+ */
+ private Random mRnd = null;
+
+ private final Object mTimerLock = new Object();
+
+ private UUIDTimer mTimer = null;
+
+ private byte[] address;
+
+ /**
+ * Constructor is private to enforce singleton access.
+ */
+ private UUIDGenerator()
+ {
+ }
+
+ /**
+ * Method used for accessing the singleton generator instance.
+ */
+ public static UUIDGenerator getInstance()
+ {
+ return UUIDGenerator.sSingleton;
+ }
+
+ /*
+ * ///////////////////////////////////////////////////// // Configuration
+ * /////////////////////////////////////////////////////
+ */
+
+ /**
+ * Method for getting the shared random number generator used for generating
+ * the UUIDs. This way the initialization cost is only taken once; access
+ * need not be synchronized (or in cases where it has to, SecureRandom takes
+ * care of it); it might even be good for getting really 'random' stuff to
+ * get shared access...
+ */
+ public final Random getRandomNumberGenerator()
+ {
+ /*
+ * Could be synchronized, but since side effects are trivial (ie.
+ * possibility of generating more than one SecureRandom, of which all but
+ * one are dumped) let's not add synchronization overhead:
+ */
+ if (mRnd == null)
+ {
+ mRnd = new SecureRandom();
+ }
+ return mRnd;
+ }
+
+ public final UUID generateTimeBasedUUID(final byte[] byteAddr)
+ {
+ byte[] contents = new byte[16];
+ int pos = 10;
+ for (int i = 0; i < 6; ++i)
+ {
+ contents[pos + i] = byteAddr[i];
+ }
+
+ synchronized (mTimerLock)
+ {
+ if (mTimer == null)
+ {
+ mTimer = new UUIDTimer(getRandomNumberGenerator());
+ }
+
+ mTimer.getTimestamp(contents);
+ }
+
+ return new UUID(UUID.TYPE_TIME_BASED, contents);
+ }
+
+ public final byte[] generateDummyAddress()
+ {
+ Random rnd = getRandomNumberGenerator();
+ byte[] dummy = new byte[6];
+ rnd.nextBytes(dummy);
+ /* Need to set the broadcast bit to indicate it's not a real
+ * address.
+ */
+ dummy[0] |= (byte)0x01;
+
+ if (UUIDGenerator.log.isDebugEnabled())
+ {
+ UUIDGenerator.log.debug("using dummy address " + UUIDGenerator.asString(dummy));
+ }
+ return dummy;
+ }
+
+ /**
+ * If running java 6 or above, returns {@link NetworkInterface#getHardwareAddress()}, else return <code>null</code>.
+ * The first hardware address is returned when iterating all the NetworkInterfaces
+ */
+ public final static byte[] getHardwareAddress()
+ {
+ Method getHardwareAddressMethod;
+ Method isUpMethod;
+ Method isLoopbackMethod;
+ Method isVirtualMethod;
+ try
+ {
+ getHardwareAddressMethod = NetworkInterface.class.getMethod("getHardwareAddress");
+ isUpMethod = NetworkInterface.class.getMethod("isUp");
+ isLoopbackMethod = NetworkInterface.class.getMethod("isLoopback");
+ isVirtualMethod = NetworkInterface.class.getMethod("isVirtual");
+ }
+ catch (Throwable t)
+ {
+ // not on Java 6 or not enough security permission
+ return null;
+ }
+
+ try
+ {
+ Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+ while (networkInterfaces.hasMoreElements())
+ {
+ NetworkInterface networkInterface = networkInterfaces.nextElement();
+ boolean up = (Boolean)isUpMethod.invoke(networkInterface);
+ boolean loopback = (Boolean)isLoopbackMethod.invoke(networkInterface);
+ boolean virtual = (Boolean)isVirtualMethod.invoke(networkInterface);
+
+ if (loopback || virtual || !up)
+ {
+ continue;
+ }
+
+ Object res = getHardwareAddressMethod.invoke(networkInterface);
+ if (res != null && res instanceof byte[])
+ {
+ byte[] address = (byte[])res;
+ byte[] paddedAddress = UUIDGenerator.getZeroPaddedSixBytes(address);
+
+ if (UUIDGenerator.isBlackList(address))
+ {
+ continue;
+ }
+
+ if (paddedAddress != null)
+ {
+ if (UUIDGenerator.log.isDebugEnabled())
+ {
+ UUIDGenerator.log.debug("using hardware address " + UUIDGenerator.asString(paddedAddress));
+ }
+ return paddedAddress;
+ }
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ }
+
+ return null;
+ }
+
+ public final SimpleString generateSimpleStringUUID()
+ {
+ return new SimpleString(generateStringUUID());
+ }
+
+ public final UUID generateUUID()
+ {
+ byte[] address = getAddressBytes();
+
+ UUID uid = generateTimeBasedUUID(address);
+
+ return uid;
+ }
+
+ public final String generateStringUUID()
+ {
+ byte[] address = getAddressBytes();
+
+ if (address == null)
+ {
+ return java.util.UUID.randomUUID().toString();
+ }
+ else
+ {
+ return generateTimeBasedUUID(address).toString();
+ }
+ }
+
+ public final static byte[] getZeroPaddedSixBytes(final byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ return null;
+ }
+ if (bytes.length > 0 && bytes.length <= 6)
+ {
+ if (bytes.length == 6)
+ {
+ return bytes;
+ }
+ else
+ {
+ // pad with zeroes to have a 6-byte array
+ byte[] paddedAddress = new byte[6];
+ System.arraycopy(bytes, 0, paddedAddress, 0, bytes.length);
+ for (int i = bytes.length; i < 6; i++)
+ {
+ paddedAddress[i] = 0;
+ }
+ return paddedAddress;
+ }
+ }
+ return null;
+ }
+
+ // Private -------------------------------------------------------
+
+ private static final boolean isBlackList(final byte[] address)
+ {
+ for (byte[] blackList : UUIDGenerator.BLACK_LIST)
+ {
+ if (Arrays.equals(address, blackList))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private final byte[] getAddressBytes()
+ {
+ if (address == null)
+ {
+ address = UUIDGenerator.getHardwareAddress();
+ if (address == null)
+ {
+ address = generateDummyAddress();
+ }
+ }
+
+ return address;
+ }
+
+ private static final String asString(final byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ return null;
+ }
+
+ String s = "";
+ for (int i = 0; i < bytes.length - 1; i++)
+ {
+ s += Integer.toHexString(bytes[i]) + ":";
+ }
+ s += bytes[bytes.length - 1];
+ return s;
+ }
+}
\ No newline at end of file
Copied: trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDTimer.java (from rev 10739, trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDTimer.java)
===================================================================
--- trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDTimer.java (rev 0)
+++ trunk/hornetq-commons/src/main/java/org/hornetq/utils/UUIDTimer.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,326 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
+ *
+ * Licensed under the License specified in the file licenses/LICENSE.txt which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.util.Random;
+
+/**
+ * UUIDTimer produces the time stamps required for time-based UUIDs. It works as
+ * outlined in the UUID specification, with following implementation:
+ * <ul>
+ * <li>Java classes can only product time stamps with maximum resolution of one
+ * millisecond (at least before JDK 1.5). To compensate, an additional counter
+ * is used, so that more than one UUID can be generated between java clock
+ * updates. Counter may be used to generate up to 10000 UUIDs for each distrinct
+ * java clock value.
+ * <li>Due to even lower clock resolution on some platforms (older Windows
+ * versions use 55 msec resolution), timestamp value can also advanced ahead of
+ * physical value within limits (by default, up 100 millisecond ahead of
+ * reported), iff necessary (ie. 10000 instances created before clock time
+ * advances).
+ * <li>As an additional precaution, counter is initialized not to 0 but to a
+ * random 8-bit number, and each time clock changes, lowest 8-bits of counter
+ * are preserved. The purpose it to make likelyhood of multi-JVM multi-instance
+ * generators to collide, without significantly reducing max. UUID generation
+ * speed. Note though that using more than one generator (from separate JVMs) is
+ * strongly discouraged, so hopefully this enhancement isn't needed. This 8-bit
+ * offset has to be reduced from total max. UUID count to preserve ordering
+ * property of UUIDs (ie. one can see which UUID was generated first for given
+ * UUID generator); the resulting 9500 UUIDs isn't much different from the
+ * optimal choice.
+ * <li>Finally, as of version 2.0 and onwards, optional external timestamp
+ * synchronization can be done. This is done similar to the way UUID
+ * specification suggests; except that since there is no way to lock the whole
+ * system, file-based locking is used. This works between multiple JVMs and Jug
+ * instances.
+ * </ul>
+ * <p>
+ * Some additional assumptions about calculating the timestamp:
+ * <ul>
+ * <li>System.currentTimeMillis() is assumed to give time offset in UTC, or at
+ * least close enough thing to get correct timestamps. The alternate route would
+ * have to go through calendar object, use TimeZone offset to get to UTC, and
+ * then modify. Using currentTimeMillis should be much faster to allow rapid
+ * UUID creation.
+ * <li>Similarly, the constant used for time offset between 1.1.1970 and start
+ * of Gregorian calendar is assumed to be correct (which seems to be the case
+ * when testing with Java calendars).
+ * </ul>
+ * <p>
+ * Note about synchronization: this class is assumed to always be called from a
+ * synchronized context (caller locks on either this object, or a similar timer
+ * lock), and so has no method synchronization.
+ */
+public class UUIDTimer
+{
+ // // // Constants
+
+ /**
+ * Since System.longTimeMillis() returns time from january 1st 1970, and
+ * UUIDs need time from the beginning of gregorian calendar (15-oct-1582),
+ * need to apply the offset:
+ */
+ private final static long kClockOffset = 0x01b21dd213814000L;
+
+ /**
+ * Also, instead of getting time in units of 100nsecs, we get something with
+ * max resolution of 1 msec... and need the multiplier as well
+ */
+ private final static long kClockMultiplier = 10000;
+
+ private final static long kClockMultiplierL = 10000L;
+
+ /**
+ * Let's allow "virtual" system time to advance at most 100 milliseconds
+ * beyond actual physical system time, before adding delays.
+ */
+ private final static long kMaxClockAdvance = 100L;
+
+ // // // Configuration
+
+ private final Random mRnd;
+
+ // // // Clock state:
+
+ /**
+ * Additional state information used to protect against anomalous cases
+ * (clock time going backwards, node id getting mixed up). Third byte is
+ * actually used for seeding counter on counter overflow.
+ */
+ private final byte[] mClockSequence = new byte[3];
+
+ /**
+ * Last physical timestamp value <code>System.currentTimeMillis()</code>
+ * returned: used to catch (and report) cases where system clock goes
+ * backwards. Is also used to limit "drifting", that is, amount timestamps
+ * used can differ from the system time value. This value is not guaranteed
+ * to be monotonically increasing.
+ */
+ private long mLastSystemTimestamp = 0L;
+
+ /**
+ * Timestamp value last used for generating a UUID (along with
+ * {@link #mClockCounter}. Usually the same as {@link #mLastSystemTimestamp},
+ * but not always (system clock moved backwards). Note that this value is
+ * guaranteed to be monotonically increasing; that is, at given absolute time
+ * points t1 and t2 (where t2 is after t1), t1 <= t2 will always hold true.
+ */
+ private long mLastUsedTimestamp = 0L;
+
+ /**
+ * Counter used to compensate inadequate resolution of JDK system timer.
+ */
+ private int mClockCounter = 0;
+
+ UUIDTimer(final Random rnd)
+ {
+ mRnd = rnd;
+ initCounters(rnd);
+ mLastSystemTimestamp = 0L;
+ // This may get overwritten by the synchronizer
+ mLastUsedTimestamp = 0L;
+ }
+
+ private void initCounters(final Random rnd)
+ {
+ /*
+ * Let's generate the clock sequence field now; as with counter, this
+ * reduces likelihood of collisions (as explained in UUID specs)
+ */
+ rnd.nextBytes(mClockSequence);
+ /*
+ * Ok, let's also initialize the counter... Counter is used to make it
+ * slightly less likely that two instances of UUIDGenerator (from separate
+ * JVMs as no more than one can be created in one JVM) would produce
+ * colliding time-based UUIDs. The practice of using multiple generators,
+ * is strongly discouraged, of course, but just in case...
+ */
+ mClockCounter = mClockSequence[2] & 0xFF;
+ }
+
+ public void getTimestamp(final byte[] uuidData)
+ {
+ // First the clock sequence:
+ uuidData[UUID.INDEX_CLOCK_SEQUENCE] = mClockSequence[0];
+ uuidData[UUID.INDEX_CLOCK_SEQUENCE + 1] = mClockSequence[1];
+
+ long systime = System.currentTimeMillis();
+
+ /*
+ * Let's first verify that the system time is not going backwards;
+ * independent of whether we can use it:
+ */
+ if (systime < mLastSystemTimestamp)
+ {
+ // Logger.logWarning("System time going backwards! (got value
+ // "+systime+", last "+mLastSystemTimestamp);
+ // Let's write it down, still
+ mLastSystemTimestamp = systime;
+ }
+
+ /*
+ * But even without it going backwards, it may be less than the last one
+ * used (when generating UUIDs fast with coarse clock resolution; or if
+ * clock has gone backwards over reboot etc).
+ */
+ if (systime <= mLastUsedTimestamp)
+ {
+ /*
+ * Can we just use the last time stamp (ok if the counter hasn't hit
+ * max yet)
+ */
+ if (mClockCounter < UUIDTimer.kClockMultiplier)
+ { // yup, still have room
+ systime = mLastUsedTimestamp;
+ }
+ else
+ { // nope, have to roll over to next value and maybe wait
+ long actDiff = mLastUsedTimestamp - systime;
+ long origTime = systime;
+ systime = mLastUsedTimestamp + 1L;
+
+ // Logger.logWarning("Timestamp over-run: need to reinitialize
+ // random sequence");
+
+ /*
+ * Clock counter is now at exactly the multiplier; no use just
+ * anding its value. So, we better get some random numbers
+ * instead...
+ */
+ initCounters(mRnd);
+
+ /*
+ * But do we also need to slow down? (to try to keep virtual time
+ * close to physical time; ie. either catch up when system clock has
+ * been moved backwards, or when coarse clock resolution has forced
+ * us to advance virtual timer too far)
+ */
+ if (actDiff >= UUIDTimer.kMaxClockAdvance)
+ {
+ UUIDTimer.slowDown(origTime, actDiff);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Clock has advanced normally; just need to make sure counter is reset
+ * to a low value (need not be 0; good to leave a small residual to
+ * further decrease collisions)
+ */
+ mClockCounter &= 0xFF;
+ }
+
+ mLastUsedTimestamp = systime;
+
+ /*
+ * Now, let's translate the timestamp to one UUID needs, 100ns unit offset
+ * from the beginning of Gregorian calendar...
+ */
+ systime *= UUIDTimer.kClockMultiplierL;
+ systime += UUIDTimer.kClockOffset;
+
+ // Plus add the clock counter:
+ systime += mClockCounter;
+ // and then increase
+ ++mClockCounter;
+
+ /*
+ * Time fields are nicely split across the UUID, so can't just linearly
+ * dump the stamp:
+ */
+ int clockHi = (int)(systime >>> 32);
+ int clockLo = (int)systime;
+
+ uuidData[UUID.INDEX_CLOCK_HI] = (byte)(clockHi >>> 24);
+ uuidData[UUID.INDEX_CLOCK_HI + 1] = (byte)(clockHi >>> 16);
+ uuidData[UUID.INDEX_CLOCK_MID] = (byte)(clockHi >>> 8);
+ uuidData[UUID.INDEX_CLOCK_MID + 1] = (byte)clockHi;
+
+ uuidData[UUID.INDEX_CLOCK_LO] = (byte)(clockLo >>> 24);
+ uuidData[UUID.INDEX_CLOCK_LO + 1] = (byte)(clockLo >>> 16);
+ uuidData[UUID.INDEX_CLOCK_LO + 2] = (byte)(clockLo >>> 8);
+ uuidData[UUID.INDEX_CLOCK_LO + 3] = (byte)clockLo;
+ }
+
+ /*
+ * /////////////////////////////////////////////////////////// // Private
+ * methods ///////////////////////////////////////////////////////////
+ */
+
+ private final static int MAX_WAIT_COUNT = 50;
+
+ /**
+ * Simple utility method to use to wait for couple of milliseconds, to let
+ * system clock hopefully advance closer to the virtual timestamps used.
+ * Delay is kept to just a millisecond or two, to prevent excessive blocking;
+ * but that should be enough to eventually synchronize physical clock with
+ * virtual clock values used for UUIDs.
+ *
+ * @param msecs
+ * Number of milliseconds to wait for from current time point
+ */
+ private final static void slowDown(final long startTime, final long actDiff)
+ {
+ /*
+ * First, let's determine how long we'd like to wait. This is based on how
+ * far ahead are we as of now.
+ */
+ long ratio = actDiff / UUIDTimer.kMaxClockAdvance;
+ long delay;
+
+ if (ratio < 2L)
+ { // 200 msecs or less
+ delay = 1L;
+ }
+ else if (ratio < 10L)
+ { // 1 second or less
+ delay = 2L;
+ }
+ else if (ratio < 600L)
+ { // 1 minute or less
+ delay = 3L;
+ }
+ else
+ {
+ delay = 5L;
+ }
+ // Logger.logWarning("Need to wait for "+delay+" milliseconds; virtual
+ // clock advanced too far in the future");
+ long waitUntil = startTime + delay;
+ int counter = 0;
+ do
+ {
+ try
+ {
+ Thread.sleep(delay);
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ delay = 1L;
+ /*
+ * This is just a sanity check: don't want an "infinite" loop if clock
+ * happened to be moved backwards by, say, an hour...
+ */
+ if (++counter > UUIDTimer.MAX_WAIT_COUNT)
+ {
+ break;
+ }
+ }
+ while (System.currentTimeMillis() < waitUntil);
+ }
+}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/api/core/PropertyConversionException.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/api/core/PropertyConversionException.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/api/core/PropertyConversionException.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,54 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.hornetq.api.core;
-
-/**
- * A PropertyConversionException is thrown by Message methods
- * when a property can not be converted to the expected type.
- *
- * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
- *
- * @see Message
- *
- */
-public class PropertyConversionException extends RuntimeException
-{
-
- // Constants -----------------------------------------------------
-
- private static final long serialVersionUID = -3010008708334904332L;
-
- // Attributes ----------------------------------------------------
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
-
- public PropertyConversionException(final String message)
- {
- super(message);
- }
-
- // Public --------------------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
-
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/Base64.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/Base64.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/Base64.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,2350 +0,0 @@
-package org.hornetq.utils;
-
-/**
- * <p>Encodes and decodes to and from Base64 notation.</p>
- * <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p>
- *
- * <p>The <tt>options</tt> parameter, which appears in a few places, is used to pass
- * several pieces of information to the encoder. In the "higher level" methods such as
- * encodeBytes( bytes, options ) the options parameter can be used to indicate such
- * things as first gzipping the bytes before encoding them, not inserting linefeeds
- * (though that breaks strict Base64 compatibility), and encoding using the URL-safe
- * and Ordered dialects.</p>
- *
- * <p>The constants defined in Base64 can be OR-ed together to combine options, so you
- * might make a call like this:</p>
- *
- * <code>String encoded = Base64.encodeBytes( mybytes, Base64.GZIP | Base64.DONT_BREAK_LINES );</code>
- *
- * <p>to compress the data before encoding it and then making the output have no newline characters.</p>
- *
- *
- * <p>
- * Change Log:
- * </p>
- * <ul>
- * <li>v2.2.2 - Fixed encodeFileToFile and decodeFileToFile to use the
- * Base64.InputStream class to encode and decode on the fly which uses
- * less memory than encoding/decoding an entire file into memory before writing.</li>
- * <li>v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug
- * when using very small files (~< 40 bytes).</li>
- * <li>v2.2 - Added some helper methods for encoding/decoding directly from
- * one file to the next. Also added a main() method to support command line
- * encoding/decoding from one file to the next. Also added these Base64 dialects:
- * <ol>
- * <li>The default is RFC3548 format.</li>
- * <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates
- * URL and file name friendly format as described in Section 4 of RFC3548.
- * http://www.faqs.org/rfcs/rfc3548.html</li>
- * <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates
- * URL and file name friendly format that preserves lexical ordering as described
- * in http://www.faqs.org/qa/rfcc-1940.html</li>
- * </ol>
- * Special thanks to Jim Kellerman at <a href="http://www.powerset.com/">http://www.powerset.com/</a>
- * for contributing the new Base64 dialects.
- * </li>
- *
- * <li>v2.1 - Cleaned up javadoc comments and unused variables and methods. Added
- * some convenience methods for reading and writing to and from files.</li>
- * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems
- * with other encodings (like EBCDIC).</li>
- * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
- * encoded data was a single byte.</li>
- * <li>v2.0 - I got rid of methods that used booleans to set options.
- * Now everything is more consolidated and cleaner. The code now detects
- * when data that's being decoded is gzip-compressed and will decompress it
- * automatically. Generally things are cleaner. You'll probably have to
- * change some method calls that you were making to support the new
- * options format (<tt>int</tt>s that you "OR" together).</li>
- * <li>v1.5.1 - Fixed bug when decompressing and decoding to a
- * byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.
- * Added the ability to "suspend" encoding in the Output Stream so
- * you can turn on and off the encoding if you need to embed base64
- * data in an otherwise "normal" stream (like an XML file).</li>
- * <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself.
- * This helps when using GZIP streams.
- * Added the ability to GZip-compress objects before encoding them.</li>
- * <li>v1.4 - Added helper methods to read/write files.</li>
- * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
- * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream
- * where last buffer being read, if not completely full, was not returned.</li>
- * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.</li>
- * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
- * </ul>
- *
- * <p>
- * I am placing this code in the Public Domain. Do with it as you will.
- * This software comes with no guarantees or warranties but with
- * plenty of well-wishing instead!
- * Please visit <a href="http://iharder.net/base64">http://iharder.net/base64</a>
- * periodically to check for updates or to contribute improvements.
- * </p>
- *
- * @author Robert Harder
- * @author rob at iharder.net
- * @version 2.2.2
- */
-public class Base64
-{
-
- /* ******** P U B L I C F I E L D S ******** */
-
- /** No options specified. Value is zero. */
- public final static int NO_OPTIONS = 0;
-
- /** Specify encoding. */
- public final static int ENCODE = 1;
-
- /** Specify decoding. */
- public final static int DECODE = 0;
-
- /** Specify that data should be gzip-compressed. */
- public final static int GZIP = 2;
-
- /** Don't break lines when encoding (violates strict Base64 specification) */
- public final static int DONT_BREAK_LINES = 8;
-
- /**
- * Encode using Base64-like encoding that is URL- and Filename-safe as described
- * in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * It is important to note that data encoded this way is <em>not</em> officially valid Base64,
- * or at the very least should not be called Base64 without also specifying that is
- * was encoded using the URL- and Filename-safe dialect.
- */
- public final static int URL_SAFE = 16;
-
- /**
- * Encode using the special "ordered" dialect of Base64 described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- public final static int ORDERED = 32;
-
- /* ******** P R I V A T E F I E L D S ******** */
-
- /** Maximum line length (76) of Base64 output. */
- private final static int MAX_LINE_LENGTH = 76;
-
- /** The equals sign (=) as a byte. */
- private final static byte EQUALS_SIGN = (byte)'=';
-
- /** The new line character (\n) as a byte. */
- private final static byte NEW_LINE = (byte)'\n';
-
- /** Preferred encoding. */
- private final static String PREFERRED_ENCODING = "UTF-8";
-
- // I think I end up not using the BAD_ENCODING indicator.
- // private final static byte BAD_ENCODING = -9; // Indicates error in encoding
- private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
-
- private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
-
- /* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
-
- /** The 64 valid Base64 values. */
- // private final static byte[] ALPHABET;
- /* Host platform me be something funny like EBCDIC, so we hardcode these values. */
- private final static byte[] _STANDARD_ALPHABET = { (byte)'A',
- (byte)'B',
- (byte)'C',
- (byte)'D',
- (byte)'E',
- (byte)'F',
- (byte)'G',
- (byte)'H',
- (byte)'I',
- (byte)'J',
- (byte)'K',
- (byte)'L',
- (byte)'M',
- (byte)'N',
- (byte)'O',
- (byte)'P',
- (byte)'Q',
- (byte)'R',
- (byte)'S',
- (byte)'T',
- (byte)'U',
- (byte)'V',
- (byte)'W',
- (byte)'X',
- (byte)'Y',
- (byte)'Z',
- (byte)'a',
- (byte)'b',
- (byte)'c',
- (byte)'d',
- (byte)'e',
- (byte)'f',
- (byte)'g',
- (byte)'h',
- (byte)'i',
- (byte)'j',
- (byte)'k',
- (byte)'l',
- (byte)'m',
- (byte)'n',
- (byte)'o',
- (byte)'p',
- (byte)'q',
- (byte)'r',
- (byte)'s',
- (byte)'t',
- (byte)'u',
- (byte)'v',
- (byte)'w',
- (byte)'x',
- (byte)'y',
- (byte)'z',
- (byte)'0',
- (byte)'1',
- (byte)'2',
- (byte)'3',
- (byte)'4',
- (byte)'5',
- (byte)'6',
- (byte)'7',
- (byte)'8',
- (byte)'9',
- (byte)'+',
- (byte)'/' };
-
- /**
- * Translates a Base64 value to either its 6-bit reconstruction value
- * or a negative number indicating some other meaning.
- **/
- private final static byte[] _STANDARD_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
- -5,
- -5, // Whitespace: Tab and Linefeed
- -9,
- -9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 14 - 26
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 33 - 42
- 62, // Plus sign at decimal 43
- -9,
- -9,
- -9, // Decimal 44 - 46
- 63, // Slash at decimal 47
- 52,
- 53,
- 54,
- 55,
- 56,
- 57,
- 58,
- 59,
- 60,
- 61, // Numbers zero through nine
- -9,
- -9,
- -9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,
- -9,
- -9, // Decimal 62 - 64
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13, // Letters 'A' through 'N'
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23,
- 24,
- 25, // Letters 'O' through 'Z'
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 91 - 96
- 26,
- 27,
- 28,
- 29,
- 30,
- 31,
- 32,
- 33,
- 34,
- 35,
- 36,
- 37,
- 38, // Letters 'a' through 'm'
- 39,
- 40,
- 41,
- 42,
- 43,
- 44,
- 45,
- 46,
- 47,
- 48,
- 49,
- 50,
- 51, // Letters 'n' through 'z'
- -9,
- -9,
- -9,
- -9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
- /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
- */
- private final static byte[] _URL_SAFE_ALPHABET = { (byte)'A',
- (byte)'B',
- (byte)'C',
- (byte)'D',
- (byte)'E',
- (byte)'F',
- (byte)'G',
- (byte)'H',
- (byte)'I',
- (byte)'J',
- (byte)'K',
- (byte)'L',
- (byte)'M',
- (byte)'N',
- (byte)'O',
- (byte)'P',
- (byte)'Q',
- (byte)'R',
- (byte)'S',
- (byte)'T',
- (byte)'U',
- (byte)'V',
- (byte)'W',
- (byte)'X',
- (byte)'Y',
- (byte)'Z',
- (byte)'a',
- (byte)'b',
- (byte)'c',
- (byte)'d',
- (byte)'e',
- (byte)'f',
- (byte)'g',
- (byte)'h',
- (byte)'i',
- (byte)'j',
- (byte)'k',
- (byte)'l',
- (byte)'m',
- (byte)'n',
- (byte)'o',
- (byte)'p',
- (byte)'q',
- (byte)'r',
- (byte)'s',
- (byte)'t',
- (byte)'u',
- (byte)'v',
- (byte)'w',
- (byte)'x',
- (byte)'y',
- (byte)'z',
- (byte)'0',
- (byte)'1',
- (byte)'2',
- (byte)'3',
- (byte)'4',
- (byte)'5',
- (byte)'6',
- (byte)'7',
- (byte)'8',
- (byte)'9',
- (byte)'-',
- (byte)'_' };
-
- /**
- * Used in decoding URL- and Filename-safe dialects of Base64.
- */
- private final static byte[] _URL_SAFE_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
- -5,
- -5, // Whitespace: Tab and Linefeed
- -9,
- -9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 14 - 26
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 62, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 52,
- 53,
- 54,
- 55,
- 56,
- 57,
- 58,
- 59,
- 60,
- 61, // Numbers zero through nine
- -9,
- -9,
- -9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,
- -9,
- -9, // Decimal 62 - 64
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13, // Letters 'A' through 'N'
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23,
- 24,
- 25, // Letters 'O' through 'Z'
- -9,
- -9,
- -9,
- -9, // Decimal 91 - 94
- 63, // Underscore at decimal 95
- -9, // Decimal 96
- 26,
- 27,
- 28,
- 29,
- 30,
- 31,
- 32,
- 33,
- 34,
- 35,
- 36,
- 37,
- 38, // Letters 'a' through 'm'
- 39,
- 40,
- 41,
- 42,
- 43,
- 44,
- 45,
- 46,
- 47,
- 48,
- 49,
- 50,
- 51, // Letters 'n' through 'z'
- -9,
- -9,
- -9,
- -9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
- /* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * I don't get the point of this technique, but it is described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- private final static byte[] _ORDERED_ALPHABET = { (byte)'-',
- (byte)'0',
- (byte)'1',
- (byte)'2',
- (byte)'3',
- (byte)'4',
- (byte)'5',
- (byte)'6',
- (byte)'7',
- (byte)'8',
- (byte)'9',
- (byte)'A',
- (byte)'B',
- (byte)'C',
- (byte)'D',
- (byte)'E',
- (byte)'F',
- (byte)'G',
- (byte)'H',
- (byte)'I',
- (byte)'J',
- (byte)'K',
- (byte)'L',
- (byte)'M',
- (byte)'N',
- (byte)'O',
- (byte)'P',
- (byte)'Q',
- (byte)'R',
- (byte)'S',
- (byte)'T',
- (byte)'U',
- (byte)'V',
- (byte)'W',
- (byte)'X',
- (byte)'Y',
- (byte)'Z',
- (byte)'_',
- (byte)'a',
- (byte)'b',
- (byte)'c',
- (byte)'d',
- (byte)'e',
- (byte)'f',
- (byte)'g',
- (byte)'h',
- (byte)'i',
- (byte)'j',
- (byte)'k',
- (byte)'l',
- (byte)'m',
- (byte)'n',
- (byte)'o',
- (byte)'p',
- (byte)'q',
- (byte)'r',
- (byte)'s',
- (byte)'t',
- (byte)'u',
- (byte)'v',
- (byte)'w',
- (byte)'x',
- (byte)'y',
- (byte)'z' };
-
- /**
- * Used in decoding the "ordered" dialect of Base64.
- */
- private final static byte[] _ORDERED_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
- -5,
- -5, // Whitespace: Tab and Linefeed
- -9,
- -9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 14 - 26
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9,
- -9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 0, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10, // Numbers zero through nine
- -9,
- -9,
- -9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,
- -9,
- -9, // Decimal 62 - 64
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23, // Letters 'A' through 'M'
- 24,
- 25,
- 26,
- 27,
- 28,
- 29,
- 30,
- 31,
- 32,
- 33,
- 34,
- 35,
- 36, // Letters 'N' through 'Z'
- -9,
- -9,
- -9,
- -9, // Decimal 91 - 94
- 37, // Underscore at decimal 95
- -9, // Decimal 96
- 38,
- 39,
- 40,
- 41,
- 42,
- 43,
- 44,
- 45,
- 46,
- 47,
- 48,
- 49,
- 50, // Letters 'a' through 'm'
- 51,
- 52,
- 53,
- 54,
- 55,
- 56,
- 57,
- 58,
- 59,
- 60,
- 61,
- 62,
- 63, // Letters 'n' through 'z'
- -9,
- -9,
- -9,
- -9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
- /* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
-
- /**
- * Returns one of the _SOMETHING_ALPHABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED and URLSAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getAlphabet(final int options)
- {
- if ((options & Base64.URL_SAFE) == Base64.URL_SAFE)
- {
- return Base64._URL_SAFE_ALPHABET;
- }
- else if ((options & Base64.ORDERED) == Base64.ORDERED)
- {
- return Base64._ORDERED_ALPHABET;
- }
- else
- {
- return Base64._STANDARD_ALPHABET;
- }
-
- } // end getAlphabet
-
- /**
- * Returns one of the _SOMETHING_DECODABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED and URL_SAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getDecodabet(final int options)
- {
- if ((options & Base64.URL_SAFE) == Base64.URL_SAFE)
- {
- return Base64._URL_SAFE_DECODABET;
- }
- else if ((options & Base64.ORDERED) == Base64.ORDERED)
- {
- return Base64._ORDERED_DECODABET;
- }
- else
- {
- return Base64._STANDARD_DECODABET;
- }
-
- } // end getAlphabet
-
- /** Defeats instantiation. */
- private Base64()
- {
- }
-
- /**
- * Encodes or decodes two files from the command line;
- * <strong>feel free to delete this method (in fact you probably should)
- * if you're embedding this code into a larger program.</strong>
- */
- public final static void main(final String[] args)
- {
- if (args.length < 3)
- {
- Base64.usage("Not enough arguments.");
- } // end if: args.length < 3
- else
- {
- String flag = args[0];
- String infile = args[1];
- String outfile = args[2];
- if (flag.equals("-e"))
- {
- Base64.encodeFileToFile(infile, outfile);
- } // end if: encode
- else if (flag.equals("-d"))
- {
- Base64.decodeFileToFile(infile, outfile);
- } // end else if: decode
- else
- {
- Base64.usage("Unknown flag: " + flag);
- } // end else
- } // end else
- } // end main
-
- /**
- * Prints command line usage.
- *
- * @param msg A message to include with usage info.
- */
- private final static void usage(final String msg)
- {
- System.err.println(msg);
- System.err.println("Usage: java Base64 -e|-d inputfile outputfile");
- } // end usage
-
- /* ******** E N C O D I N G M E T H O D S ******** */
-
- /**
- * Encodes up to the first three bytes of array <var>threeBytes</var>
- * and returns a four-byte array in Base64 notation.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.
- * The array <var>threeBytes</var> needs only be as big as
- * <var>numSigBytes</var>.
- * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
- *
- * @param b4 A reusable byte array to reduce array instantiation
- * @param threeBytes the array to convert
- * @param numSigBytes the number of significant bytes in your array
- * @return four byte array in Base64 notation.
- * @since 1.5.1
- */
- private static byte[] encode3to4(final byte[] b4, final byte[] threeBytes, final int numSigBytes, final int options)
- {
- Base64.encode3to4(threeBytes, 0, numSigBytes, b4, 0, options);
- return b4;
- } // end encode3to4
-
- /**
- * <p>Encodes up to three bytes of the array <var>source</var>
- * and writes the resulting four Base64 bytes to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 3 for
- * the <var>source</var> array or <var>destOffset</var> + 4 for
- * the <var>destination</var> array.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.</p>
- * <p>This is the lowest level of the encoding methods with
- * all possible parameters.</p>
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param numSigBytes the number of significant bytes in your array
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @return the <var>destination</var> array
- * @since 1.3
- */
- private static byte[] encode3to4(final byte[] source,
- final int srcOffset,
- final int numSigBytes,
- final byte[] destination,
- final int destOffset,
- final int options)
- {
- byte[] ALPHABET = Base64.getAlphabet(options);
-
- // 1 2 3
- // 01234567890123456789012345678901 Bit position
- // --------000000001111111122222222 Array position from threeBytes
- // --------| || || || | Six bit groups to index ALPHABET
- // >>18 >>12 >> 6 >> 0 Right shift necessary
- // 0x3f 0x3f 0x3f Additional AND
-
- // Create buffer with zero-padding if there are only one or two
- // significant bytes passed in the array.
- // We have to shift left 24 in order to flush out the 1's that appear
- // when Java treats a value as negative that is cast from a byte to an int.
- int inBuff = (numSigBytes > 0 ? source[srcOffset] << 24 >>> 8 : 0) | (numSigBytes > 1 ? source[srcOffset + 1] << 24 >>> 16
- : 0) |
- (numSigBytes > 2 ? source[srcOffset + 2] << 24 >>> 24 : 0);
-
- switch (numSigBytes)
- {
- case 3:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
- destination[destOffset + 2] = ALPHABET[inBuff >>> 6 & 0x3f];
- destination[destOffset + 3] = ALPHABET[inBuff & 0x3f];
- return destination;
-
- case 2:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
- destination[destOffset + 2] = ALPHABET[inBuff >>> 6 & 0x3f];
- destination[destOffset + 3] = Base64.EQUALS_SIGN;
- return destination;
-
- case 1:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[inBuff >>> 12 & 0x3f];
- destination[destOffset + 2] = Base64.EQUALS_SIGN;
- destination[destOffset + 3] = Base64.EQUALS_SIGN;
- return destination;
-
- default:
- return destination;
- } // end switch
- } // end encode3to4
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * The object is not GZip-compressed before being encoded.
- *
- * @param serializableObject The object to encode
- * @return The Base64-encoded object
- * @since 1.4
- */
- public static String encodeObject(final java.io.Serializable serializableObject)
- {
- return Base64.encodeObject(serializableObject, Base64.NO_OPTIONS);
- } // end encodeObject
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- * @param serializableObject The object to encode
- * @param options Specified options
- * @return The Base64-encoded object
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeObject(final java.io.Serializable serializableObject, final int options)
- {
- // Streams
- java.io.ByteArrayOutputStream baos = null;
- java.io.OutputStream b64os = null;
- java.io.ObjectOutputStream oos = null;
- java.util.zip.GZIPOutputStream gzos = null;
-
- // Isolate options
- int gzip = options & Base64.GZIP;
- int dontBreakLines = options & Base64.DONT_BREAK_LINES;
-
- try
- {
- // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream(baos, Base64.ENCODE | options);
-
- // GZip?
- if (gzip == Base64.GZIP)
- {
- gzos = new java.util.zip.GZIPOutputStream(b64os);
- oos = new java.io.ObjectOutputStream(gzos);
- } // end if: gzip
- else
- {
- oos = new java.io.ObjectOutputStream(b64os);
- }
-
- oos.writeObject(serializableObject);
- } // end try
- catch (java.io.IOException e)
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try
- {
- oos.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- gzos.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- b64os.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- baos.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String(baos.toByteArray(), Base64.PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String(baos.toByteArray());
- } // end catch
-
- } // end encode
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @since 1.4
- */
- public static String encodeBytes(final byte[] source)
- {
- return Base64.encodeBytes(source, 0, source.length, Base64.NO_OPTIONS);
- } // end encodeBytes
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param options Specified options
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes(final byte[] source, final int options)
- {
- return Base64.encodeBytes(source, 0, source.length, options);
- } // end encodeBytes
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @since 1.4
- */
- public static String encodeBytes(final byte[] source, final int off, final int len)
- {
- return Base64.encodeBytes(source, off, len, Base64.NO_OPTIONS);
- } // end encodeBytes
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param options options alphabet type is pulled from this (standard, url-safe, ordered)
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes(final byte[] source, final int off, final int len, final int options)
- {
- // Isolate options
- int dontBreakLines = options & Base64.DONT_BREAK_LINES;
- int gzip = options & Base64.GZIP;
-
- // Compress?
- if (gzip == Base64.GZIP)
- {
- java.io.ByteArrayOutputStream baos = null;
- java.util.zip.GZIPOutputStream gzos = null;
- Base64.OutputStream b64os = null;
-
- try
- {
- // GZip -> Base64 -> ByteArray
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream(baos, Base64.ENCODE | options);
- gzos = new java.util.zip.GZIPOutputStream(b64os);
-
- gzos.write(source, off, len);
- gzos.close();
- } // end try
- catch (java.io.IOException e)
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try
- {
- gzos.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- b64os.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- baos.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String(baos.toByteArray(), Base64.PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String(baos.toByteArray());
- } // end catch
- } // end if: compress
-
- // Else, don't compress. Better not to use streams at all then.
- else
- {
- // Convert option to boolean in way that code likes it.
- boolean breakLines = dontBreakLines == 0;
-
- int len43 = len * 4 / 3;
- byte[] outBuff = new byte[len43 + (len % 3 > 0 ? 4 : 0) // Account for padding
- +
- (breakLines ? len43 / Base64.MAX_LINE_LENGTH : 0)]; // New lines
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for (; d < len2; d += 3, e += 4)
- {
- Base64.encode3to4(source, d + off, 3, outBuff, e, options);
-
- lineLength += 4;
- if (breakLines && lineLength == Base64.MAX_LINE_LENGTH)
- {
- outBuff[e + 4] = Base64.NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
-
- if (d < len)
- {
- Base64.encode3to4(source, d + off, len - d, outBuff, e, options);
- e += 4;
- } // end if: some padding needed
-
- // Return value according to relevant encoding.
- try
- {
- return new String(outBuff, 0, e, Base64.PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String(outBuff, 0, e);
- } // end catch
-
- } // end else: don't compress
-
- } // end encodeBytes
-
- /* ******** D E C O D I N G M E T H O D S ******** */
-
- /**
- * Decodes four bytes from array <var>source</var>
- * and writes the resulting bytes (up to three of them)
- * to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 4 for
- * the <var>source</var> array or <var>destOffset</var> + 3 for
- * the <var>destination</var> array.
- * This method returns the actual number of bytes that
- * were converted from the Base64 encoding.
- * <p>This is the lowest level of the decoding methods with
- * all possible parameters.</p>
- *
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @param options alphabet type is pulled from this (standard, url-safe, ordered)
- * @return the number of decoded bytes converted
- * @since 1.3
- */
- private static int decode4to3(final byte[] source,
- final int srcOffset,
- final byte[] destination,
- final int destOffset,
- final int options)
- {
- byte[] DECODABET = Base64.getDecodabet(options);
-
- // Example: Dk==
- if (source[srcOffset + 2] == Base64.EQUALS_SIGN)
- {
- // Two ways to do the same thing. Don't know which way I like best.
- // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
- int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12;
-
- destination[destOffset] = (byte)(outBuff >>> 16);
- return 1;
- }
-
- // Example: DkL=
- else if (source[srcOffset + 3] == Base64.EQUALS_SIGN)
- {
- // Two ways to do the same thing. Don't know which way I like best.
- // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
- int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12 |
- (DECODABET[source[srcOffset + 2]] & 0xFF) << 6;
-
- destination[destOffset] = (byte)(outBuff >>> 16);
- destination[destOffset + 1] = (byte)(outBuff >>> 8);
- return 2;
- }
-
- // Example: DkLE
- else
- {
- try
- {
- // Two ways to do the same thing. Don't know which way I like best.
- // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
- // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
- int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | (DECODABET[source[srcOffset + 1]] & 0xFF) << 12 |
- (DECODABET[source[srcOffset + 2]] & 0xFF) << 6 |
- DECODABET[source[srcOffset + 3]] &
- 0xFF;
-
- destination[destOffset] = (byte)(outBuff >> 16);
- destination[destOffset + 1] = (byte)(outBuff >> 8);
- destination[destOffset + 2] = (byte)outBuff;
-
- return 3;
- }
- catch (Exception e)
- {
- System.out.println("" + source[srcOffset] + ": " + DECODABET[source[srcOffset]]);
- System.out.println("" + source[srcOffset + 1] + ": " + DECODABET[source[srcOffset + 1]]);
- System.out.println("" + source[srcOffset + 2] + ": " + DECODABET[source[srcOffset + 2]]);
- System.out.println("" + source[srcOffset + 3] + ": " + DECODABET[source[srcOffset + 3]]);
- return -1;
- } // end catch
- }
- } // end decodeToBytes
-
- /**
- * Very low-level access to decoding ASCII characters in
- * the form of a byte array. Does not support automatically
- * gunzipping or any other "fancy" features.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @return decoded data
- * @since 1.3
- */
- public static byte[] decode(final byte[] source, final int off, final int len, final int options)
- {
- byte[] DECODABET = Base64.getDecodabet(options);
-
- int len34 = len * 3 / 4;
- byte[] outBuff = new byte[len34]; // Upper limit on size of output
- int outBuffPosn = 0;
-
- byte[] b4 = new byte[4];
- int b4Posn = 0;
- int i = 0;
- byte sbiCrop = 0;
- byte sbiDecode = 0;
- for (i = off; i < off + len; i++)
- {
- sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
- sbiDecode = DECODABET[sbiCrop];
-
- if (sbiDecode >= Base64.WHITE_SPACE_ENC) // White space, Equals sign or better
- {
- if (sbiDecode >= Base64.EQUALS_SIGN_ENC)
- {
- b4[b4Posn++] = sbiCrop;
- if (b4Posn > 3)
- {
- outBuffPosn += Base64.decode4to3(b4, 0, outBuff, outBuffPosn, options);
- b4Posn = 0;
-
- // If that was the equals sign, break out of 'for' loop
- if (sbiCrop == Base64.EQUALS_SIGN)
- {
- break;
- }
- } // end if: quartet built
-
- } // end if: equals sign or better
-
- } // end if: white space, equals sign or better
- else
- {
- System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
- return null;
- } // end else:
- } // each input character
-
- byte[] out = new byte[outBuffPosn];
- System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
- return out;
- } // end decode
-
- /**
- * Decodes data from Base64 notation, automatically
- * detecting gzip-compressed data and decompressing it.
- *
- * @param s the string to decode
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode(final String s)
- {
- return Base64.decode(s, Base64.NO_OPTIONS);
- }
-
- /**
- * Decodes data from Base64 notation, automatically
- * detecting gzip-compressed data and decompressing it.
- *
- * @param s the string to decode
- * @param options encode options such as URL_SAFE
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode(final String s, final int options)
- {
- byte[] bytes;
- try
- {
- bytes = s.getBytes(Base64.PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uee)
- {
- bytes = s.getBytes();
- } // end catch
- // </change>
-
- // Decode
- bytes = Base64.decode(bytes, 0, bytes.length, options);
-
- // Check to see if it's gzip-compressed
- // GZIP Magic Two-Byte Number: 0x8b1f (35615)
- if (bytes != null && bytes.length >= 4)
- {
-
- int head = bytes[0] & 0xff | bytes[1] << 8 & 0xff00;
- if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head)
- {
- java.io.ByteArrayInputStream bais = null;
- java.util.zip.GZIPInputStream gzis = null;
- java.io.ByteArrayOutputStream baos = null;
- byte[] buffer = new byte[2048];
- int length = 0;
-
- try
- {
- baos = new java.io.ByteArrayOutputStream();
- bais = new java.io.ByteArrayInputStream(bytes);
- gzis = new java.util.zip.GZIPInputStream(bais);
-
- while ((length = gzis.read(buffer)) >= 0)
- {
- baos.write(buffer, 0, length);
- } // end while: reading input
-
- // No error? Get new bytes.
- bytes = baos.toByteArray();
-
- } // end try
- catch (java.io.IOException e)
- {
- // Just return originally-decoded bytes
- } // end catch
- finally
- {
- try
- {
- baos.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- gzis.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- bais.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- } // end if: gzipped
- } // end if: bytes.length >= 2
-
- return bytes;
- } // end decode
-
- /**
- * Attempts to decode Base64 data and deserialize a Java
- * Object within. Returns <tt>null</tt> if there was an error.
- *
- * @param encodedObject The Base64 data to decode
- * @return The decoded and deserialized object
- * @since 1.5
- */
- public static Object decodeToObject(final String encodedObject)
- {
- // Decode and gunzip if necessary
- byte[] objBytes = Base64.decode(encodedObject);
-
- java.io.ByteArrayInputStream bais = null;
- java.io.ObjectInputStream ois = null;
- Object obj = null;
-
- try
- {
- bais = new java.io.ByteArrayInputStream(objBytes);
- ois = new java.io.ObjectInputStream(bais);
-
- obj = ois.readObject();
- } // end try
- catch (java.io.IOException e)
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- catch (java.lang.ClassNotFoundException e)
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- finally
- {
- try
- {
- bais.close();
- }
- catch (Exception e)
- {
- }
- try
- {
- ois.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- return obj;
- } // end decodeObject
-
- /**
- * Convenience method for encoding data to a file.
- *
- * @param dataToEncode byte array of data to encode in base64 form
- * @param filename Filename for saving encoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean encodeToFile(final byte[] dataToEncode, final String filename)
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
- bos.write(dataToEncode);
- success = true;
- } // end try
- catch (java.io.IOException e)
- {
-
- success = false;
- } // end catch: IOException
- finally
- {
- try
- {
- bos.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- return success;
- } // end encodeToFile
-
- /**
- * Convenience method for decoding data to a file.
- *
- * @param dataToDecode Base64-encoded data as a string
- * @param filename Filename for saving decoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean decodeToFile(final String dataToDecode, final String filename)
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE);
- bos.write(dataToDecode.getBytes(Base64.PREFERRED_ENCODING));
- success = true;
- } // end try
- catch (java.io.IOException e)
- {
- success = false;
- } // end catch: IOException
- finally
- {
- try
- {
- bos.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- return success;
- } // end decodeToFile
-
- /**
- * Convenience method for reading a base64-encoded
- * file and decoding it.
- *
- * @param filename Filename for reading encoded data
- * @return decoded byte array or null if unsuccessful
- *
- * @since 2.1
- */
- public static byte[] decodeFromFile(final String filename)
- {
- byte[] decodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File(filename);
- byte[] buffer = null;
- int length = 0;
- int numBytes = 0;
-
- // Check for size of file
- if (file.length() > Integer.MAX_VALUE)
- {
- System.err.println("File is too big for this convenience method (" + file.length() + " bytes).");
- return null;
- } // end if: file too big for int index
- buffer = new byte[(int)file.length()];
-
- // Open a stream
- bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.DECODE);
-
- // Read until done
- while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
- {
- length += numBytes;
- }
-
- // Save in a variable to return
- decodedData = new byte[length];
- System.arraycopy(buffer, 0, decodedData, 0, length);
-
- } // end try
- catch (java.io.IOException e)
- {
- System.err.println("Error decoding from file " + filename);
- } // end catch: IOException
- finally
- {
- try
- {
- bis.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- return decodedData;
- } // end decodeFromFile
-
- /**
- * Convenience method for reading a binary file
- * and base64-encoding it.
- *
- * @param filename Filename for reading binary data
- * @return base64-encoded string or null if unsuccessful
- *
- * @since 2.1
- */
- public static String encodeFromFile(final String filename)
- {
- String encodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File(filename);
- byte[] buffer = new byte[Math.max((int)(file.length() * 1.4), 40)]; // Need max() for math on small files
- // (v2.2.1)
- int length = 0;
- int numBytes = 0;
-
- // Open a stream
- bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.ENCODE);
-
- // Read until done
- while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
- {
- length += numBytes;
- }
-
- // Save in a variable to return
- encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
-
- } // end try
- catch (java.io.IOException e)
- {
- System.err.println("Error encoding from file " + filename);
- } // end catch: IOException
- finally
- {
- try
- {
- bis.close();
- }
- catch (Exception e)
- {
- }
- } // end finally
-
- return encodedData;
- } // end encodeFromFile
-
- /**
- * Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
- *
- * @param infile Input file
- * @param outfile Output file
- * @return true if the operation is successful
- * @since 2.2
- */
- public static boolean encodeFileToFile(final String infile, final String outfile)
- {
- boolean success = false;
- java.io.InputStream in = null;
- java.io.OutputStream out = null;
- try
- {
- in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)),
- Base64.ENCODE);
- out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
- byte[] buffer = new byte[65536]; // 64K
- int read = -1;
- while ((read = in.read(buffer)) >= 0)
- {
- out.write(buffer, 0, read);
- } // end while: through file
- success = true;
- }
- catch (java.io.IOException exc)
- {
- exc.printStackTrace();
- }
- finally
- {
- try
- {
- in.close();
- }
- catch (Exception exc)
- {
- }
- try
- {
- out.close();
- }
- catch (Exception exc)
- {
- }
- } // end finally
-
- return success;
- } // end encodeFileToFile
-
- /**
- * Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
- *
- * @param infile Input file
- * @param outfile Output file
- * @return true if the operation is successful
- * @since 2.2
- */
- public static boolean decodeFileToFile(final String infile, final String outfile)
- {
- boolean success = false;
- java.io.InputStream in = null;
- java.io.OutputStream out = null;
- try
- {
- in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)),
- Base64.DECODE);
- out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
- byte[] buffer = new byte[65536]; // 64K
- int read = -1;
- while ((read = in.read(buffer)) >= 0)
- {
- out.write(buffer, 0, read);
- } // end while: through file
- success = true;
- }
- catch (java.io.IOException exc)
- {
- exc.printStackTrace();
- }
- finally
- {
- try
- {
- in.close();
- }
- catch (Exception exc)
- {
- }
- try
- {
- out.close();
- }
- catch (Exception exc)
- {
- }
- } // end finally
-
- return success;
- } // end decodeFileToFile
-
- /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
-
- /**
- * A {@link Base64.InputStream} will read data from another
- * <tt>java.io.InputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class InputStream extends java.io.FilterInputStream
- {
- private final boolean encode; // Encoding or decoding
-
- private int position; // Current position in the buffer
-
- private final byte[] buffer; // Small buffer holding converted data
-
- private final int bufferLength; // Length of buffer (3 or 4)
-
- private int numSigBytes; // Number of meaningful bytes in the buffer
-
- private int lineLength;
-
- private final boolean breakLines; // Break lines at less than 80 characters
-
- private final int options; // Record options used to create the stream.
-
- private final byte[] alphabet; // Local copies to avoid extra method calls
-
- private final byte[] decodabet; // Local copies to avoid extra method calls
-
- /**
- * Constructs a {@link Base64.InputStream} in DECODE mode.
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @since 1.3
- */
- public InputStream(final java.io.InputStream in)
- {
- this(in, Base64.DECODE);
- } // end constructor
-
- /**
- * Constructs a {@link Base64.InputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
- *
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @param options Specified options
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public InputStream(final java.io.InputStream in, final int options)
- {
- super(in);
- breakLines = (options & Base64.DONT_BREAK_LINES) != Base64.DONT_BREAK_LINES;
- encode = (options & Base64.ENCODE) == Base64.ENCODE;
- bufferLength = encode ? 4 : 3;
- buffer = new byte[bufferLength];
- position = -1;
- lineLength = 0;
- this.options = options; // Record for later, mostly to determine which alphabet to use
- alphabet = Base64.getAlphabet(options);
- decodabet = Base64.getDecodabet(options);
- } // end constructor
-
- /**
- * Reads enough of the input stream to convert
- * to/from Base64 and returns the next byte.
- *
- * @return next byte
- * @since 1.3
- */
- @Override
- public int read() throws java.io.IOException
- {
- // Do we need to get data?
- if (position < 0)
- {
- if (encode)
- {
- byte[] b3 = new byte[3];
- int numBinaryBytes = 0;
- for (int i = 0; i < 3; i++)
- {
- try
- {
- int b = in.read();
-
- // If end of stream, b is -1.
- if (b >= 0)
- {
- b3[i] = (byte)b;
- numBinaryBytes++;
- } // end if: not end of stream
-
- } // end try: read
- catch (java.io.IOException e)
- {
- // Only a problem if we got no data at all.
- if (i == 0)
- {
- throw e;
- }
-
- } // end catch
- } // end for: each needed input byte
-
- if (numBinaryBytes > 0)
- {
- Base64.encode3to4(b3, 0, numBinaryBytes, buffer, 0, options);
- position = 0;
- numSigBytes = 4;
- } // end if: got data
- else
- {
- return -1;
- }
- } // end if: encoding
-
- // Else decoding
- else
- {
- byte[] b4 = new byte[4];
- int i = 0;
- for (i = 0; i < 4; i++)
- {
- // Read four "meaningful" bytes:
- int b = 0;
- do
- {
- b = in.read();
- }
- while (b >= 0 && decodabet[b & 0x7f] <= Base64.WHITE_SPACE_ENC);
-
- if (b < 0)
- {
- break; // Reads a -1 if end of stream
- }
-
- b4[i] = (byte)b;
- } // end for: each needed input byte
-
- if (i == 4)
- {
- numSigBytes = Base64.decode4to3(b4, 0, buffer, 0, options);
- position = 0;
- } // end if: got four characters
- else if (i == 0)
- {
- return -1;
- }
- else
- {
- // Must have broken out from above.
- throw new java.io.IOException("Improperly padded Base64 input.");
- }
-
- } // end else: decode
- } // end else: get data
-
- // Got data?
- if (position >= 0)
- {
- // End of relevant data?
- if ( /*!encode &&*/position >= numSigBytes)
- {
- return -1;
- }
-
- if (encode && breakLines && lineLength >= Base64.MAX_LINE_LENGTH)
- {
- lineLength = 0;
- return '\n';
- } // end if
- else
- {
- lineLength++; // This isn't important when decoding
- // but throwing an extra "if" seems
- // just as wasteful.
-
- int b = buffer[position++];
-
- if (position >= bufferLength)
- {
- position = -1;
- }
-
- return b & 0xFF; // This is how you "cast" a byte that's
- // intended to be unsigned.
- } // end else
- } // end if: position >= 0
- else
- {
- // When JDK1.4 is more accepted, use an assertion here.
- throw new java.io.IOException("Error in Base64 code reading stream.");
- }
- } // end read
-
- /**
- * Calls {@link #read()} repeatedly until the end of stream
- * is reached or <var>len</var> bytes are read.
- * Returns number of bytes read into array or -1 if
- * end of stream is encountered.
- *
- * @param dest array to hold values
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @return bytes read into array or -1 if end of stream is encountered.
- * @since 1.3
- */
- @Override
- public int read(final byte[] dest, final int off, final int len) throws java.io.IOException
- {
- int i;
- int b;
- for (i = 0; i < len; i++)
- {
- b = read();
-
- // if( b < 0 && i == 0 )
- // return -1;
-
- if (b >= 0)
- {
- dest[off + i] = (byte)b;
- }
- else if (i == 0)
- {
- return -1;
- }
- else
- {
- break; // Out of 'for' loop
- }
- } // end for: each byte read
- return i;
- } // end read
-
- } // end inner class InputStream
-
- /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
-
- /**
- * A {@link Base64.OutputStream} will write data to another
- * <tt>java.io.OutputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class OutputStream extends java.io.FilterOutputStream
- {
- private final boolean encode;
-
- private int position;
-
- private byte[] buffer;
-
- private final int bufferLength;
-
- private int lineLength;
-
- private final boolean breakLines;
-
- private final byte[] b4; // Scratch used in a few places
-
- private boolean suspendEncoding;
-
- private final int options; // Record for later
-
- private final byte[] alphabet; // Local copies to avoid extra method calls
-
- private final byte[] decodabet; // Local copies to avoid extra method calls
-
- /**
- * Constructs a {@link Base64.OutputStream} in ENCODE mode.
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
- * @since 1.3
- */
- public OutputStream(final java.io.OutputStream out)
- {
- this(out, Base64.ENCODE);
- } // end constructor
-
- /**
- * Constructs a {@link Base64.OutputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
- * @param options Specified options.
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 1.3
- */
- public OutputStream(final java.io.OutputStream out, final int options)
- {
- super(out);
- breakLines = (options & Base64.DONT_BREAK_LINES) != Base64.DONT_BREAK_LINES;
- encode = (options & Base64.ENCODE) == Base64.ENCODE;
- bufferLength = encode ? 3 : 4;
- buffer = new byte[bufferLength];
- position = 0;
- lineLength = 0;
- suspendEncoding = false;
- b4 = new byte[4];
- this.options = options;
- alphabet = Base64.getAlphabet(options);
- decodabet = Base64.getDecodabet(options);
- } // end constructor
-
- /**
- * Writes the byte to the output stream after
- * converting to/from Base64 notation.
- * When encoding, bytes are buffered three
- * at a time before the output stream actually
- * gets a write() call.
- * When decoding, bytes are buffered four
- * at a time.
- *
- * @param theByte the byte to write
- * @since 1.3
- */
- @Override
- public void write(final int theByte) throws java.io.IOException
- {
- // Encoding suspended?
- if (suspendEncoding)
- {
- super.out.write(theByte);
- return;
- } // end if: supsended
-
- // Encode?
- if (encode)
- {
- buffer[position++] = (byte)theByte;
- if (position >= bufferLength) // Enough to encode.
- {
- out.write(Base64.encode3to4(b4, buffer, bufferLength, options));
-
- lineLength += 4;
- if (breakLines && lineLength >= Base64.MAX_LINE_LENGTH)
- {
- out.write(Base64.NEW_LINE);
- lineLength = 0;
- } // end if: end of line
-
- position = 0;
- } // end if: enough to output
- } // end if: encoding
-
- // Else, Decoding
- else
- {
- // Meaningful Base64 character?
- if (decodabet[theByte & 0x7f] > Base64.WHITE_SPACE_ENC)
- {
- buffer[position++] = (byte)theByte;
- if (position >= bufferLength) // Enough to output.
- {
- int len = Base64.decode4to3(buffer, 0, b4, 0, options);
- out.write(b4, 0, len);
- // out.write( Base64.decode4to3( buffer ) );
- position = 0;
- } // end if: enough to output
- } // end if: meaningful base64 character
- else if (decodabet[theByte & 0x7f] != Base64.WHITE_SPACE_ENC)
- {
- throw new java.io.IOException("Invalid character in Base64 data.");
- }
- } // end else: decoding
- } // end write
-
- /**
- * Calls {@link #write(int)} repeatedly until <var>len</var>
- * bytes are written.
- *
- * @param theBytes array from which to read bytes
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @since 1.3
- */
- @Override
- public void write(final byte[] theBytes, final int off, final int len) throws java.io.IOException
- {
- // Encoding suspended?
- if (suspendEncoding)
- {
- super.out.write(theBytes, off, len);
- return;
- } // end if: supsended
-
- for (int i = 0; i < len; i++)
- {
- write(theBytes[off + i]);
- } // end for: each byte written
-
- } // end write
-
- /**
- * Method added by PHIL. [Thanks, PHIL. -Rob]
- * This pads the buffer without closing the stream.
- */
- public void flushBase64() throws java.io.IOException
- {
- if (position > 0)
- {
- if (encode)
- {
- out.write(Base64.encode3to4(b4, buffer, position, options));
- position = 0;
- } // end if: encoding
- else
- {
- throw new java.io.IOException("Base64 input not properly padded.");
- }
- } // end if: buffer partially full
-
- } // end flush
-
- /**
- * Flushes and closes (I think, in the superclass) the stream.
- *
- * @since 1.3
- */
- @Override
- public void close() throws java.io.IOException
- {
- // 1. Ensure that pending characters are written
- flushBase64();
-
- // 2. Actually close the stream
- // Base class both flushes and closes.
- super.close();
-
- buffer = null;
- out = null;
- } // end close
-
- /**
- * Suspends encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void suspendEncoding() throws java.io.IOException
- {
- flushBase64();
- suspendEncoding = true;
- } // end suspendEncoding
-
- /**
- * Resumes encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void resumeEncoding()
- {
- suspendEncoding = false;
- } // end resumeEncoding
-
- } // end inner class OutputStream
-
-} // end class Base64
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentHashSet.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentHashSet.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentHashSet.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,92 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import java.util.AbstractSet;
-import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- *
- * A ConcurrentHashSet.
- *
- * Offers same concurrency as ConcurrentHashMap but for a Set
- *
- * @author <a href="tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1935 $</tt>
- *
- * $Id: ConcurrentReaderHashSet.java 1935 2007-01-09 23:29:20Z clebert.suconic at jboss.com $
- */
-public class ConcurrentHashSet<E> extends AbstractSet<E> implements ConcurrentSet<E>
-{
- private final ConcurrentMap<E, Object> theMap;
-
- private static final Object dummy = new Object();
-
- public ConcurrentHashSet()
- {
- theMap = new ConcurrentHashMap<E, Object>();
- }
-
- @Override
- public int size()
- {
- return theMap.size();
- }
-
- @Override
- public Iterator<E> iterator()
- {
- return theMap.keySet().iterator();
- }
-
- @Override
- public boolean isEmpty()
- {
- return theMap.isEmpty();
- }
-
- @Override
- public boolean add(final E o)
- {
- return theMap.put(o, ConcurrentHashSet.dummy) == null;
- }
-
- @Override
- public boolean contains(final Object o)
- {
- return theMap.containsKey(o);
- }
-
- @Override
- public void clear()
- {
- theMap.clear();
- }
-
- @Override
- public boolean remove(final Object o)
- {
- return theMap.remove(o) == ConcurrentHashSet.dummy;
- }
-
- public boolean addIfAbsent(final E o)
- {
- Object obj = theMap.putIfAbsent(o, ConcurrentHashSet.dummy);
-
- return obj == null;
- }
-
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentSet.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentSet.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/ConcurrentSet.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import java.util.Set;
-
-/**
- *
- * A ConcurrentSet
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- *
- * @param <E>
- */
-public interface ConcurrentSet<E> extends Set<E>
-{
- boolean addIfAbsent(E o);
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/HornetQThreadFactory.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/HornetQThreadFactory.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/HornetQThreadFactory.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,101 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-package org.hornetq.utils;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.hornetq.core.logging.Logger;
-
-/**
- *
- * A HornetQThreadFactory
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- *
- */
-public class HornetQThreadFactory implements ThreadFactory
-{
- private static final Logger log = Logger.getLogger(HornetQThreadFactory.class);
-
- private final ThreadGroup group;
-
- private final AtomicInteger threadCount = new AtomicInteger(0);
-
- private final int threadPriority;
-
- private final boolean daemon;
-
- private final ClassLoader tccl;
-
- public HornetQThreadFactory(final String groupName, final boolean daemon, final ClassLoader tccl)
- {
- this(groupName, Thread.NORM_PRIORITY, daemon, tccl);
- }
-
- public HornetQThreadFactory(final String groupName, final int threadPriority, final boolean daemon, final ClassLoader tccl)
- {
- group = new ThreadGroup(groupName + "-" + System.identityHashCode(this));
-
- this.threadPriority = threadPriority;
-
- this.tccl = tccl;
-
- this.daemon = daemon;
- }
-
- public Thread newThread(final Runnable command)
- {
- final Thread t;
- // attach the thread to a group only if there is no security manager:
- // when sandboxed, the code does not have the RuntimePermission modifyThreadGroup
- if (System.getSecurityManager() == null)
- {
- t = new Thread(group, command, "Thread-" + threadCount.getAndIncrement() + " (group:" + group.getName() + ")");
- }
- else
- {
- t = new Thread(command, "Thread-" + threadCount.getAndIncrement());
- }
-
- AccessController.doPrivileged(new PrivilegedAction<Object>()
- {
- public Object run()
- {
- t.setDaemon(daemon);
- t.setPriority(threadPriority);
- return null;
- }
- });
-
- try
- {
- AccessController.doPrivileged(new PrivilegedAction<Object>()
- {
- public Object run()
- {
- t.setContextClassLoader(tccl);
- return null;
- }
- });
- }
- catch (java.security.AccessControlException e)
- {
- log.warn("Missing privileges to set Thread Context Class Loader on Thread Factory. Using current Thread Context Class Loader");
- }
-
- return t;
- }
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/ReusableLatch.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/ReusableLatch.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/ReusableLatch.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,156 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.AbstractQueuedSynchronizer;
-
-/**
- *
- * <p>This class will use the framework provided to by AbstractQueuedSynchronizer.</p>
- * <p>AbstractQueuedSynchronizer is the framework for any sort of concurrent synchronization, such as Semaphores, events, etc, based on AtomicIntegers.</p>
- *
- * <p>This class works just like CountDownLatch, with the difference you can also increase the counter</p>
- *
- * <p>It could be used for sync points when one process is feeding the latch while another will wait when everything is done. (e.g. waiting IO completions to finish)</p>
- *
- * <p>On HornetQ we have the requirement of increment and decrement a counter until the user fires a ready event (commit). At that point we just act as a regular countDown.</p>
- *
- * <p>Note: This latch is reusable. Once it reaches zero, you can call up again, and reuse it on further waits.</p>
- *
- * <p>For example: prepareTransaction will wait for the current completions, and further adds will be called on the latch. Later on when commit is called you can reuse the same latch.</p>
- *
- * @author Clebert Suconic
- * */
-public class ReusableLatch
-{
- /**
- * Look at the doc and examples provided by AbstractQueuedSynchronizer for more information
- * @see AbstractQueuedSynchronizer*/
- @SuppressWarnings("serial")
- private static class CountSync extends AbstractQueuedSynchronizer
- {
- public CountSync(int count)
- {
- setState(count);
- }
-
- public int getCount()
- {
- return getState();
- }
-
- public void setCount(final int count)
- {
- setState(count);
- }
-
- @Override
- public int tryAcquireShared(final int numberOfAqcquires)
- {
- return getState() == 0 ? 1 : -1;
- }
-
- public void add()
- {
- for (;;)
- {
- int actualState = getState();
- int newState = actualState + 1;
- if (compareAndSetState(actualState, newState))
- {
- return;
- }
- }
- }
-
- @Override
- public boolean tryReleaseShared(final int numberOfReleases)
- {
- for (;;)
- {
- int actualState = getState();
- if (actualState == 0)
- {
- return true;
- }
-
- int newState = actualState - numberOfReleases;
-
- if (newState < 0)
- {
- newState = 0;
- }
-
- if (compareAndSetState(actualState, newState))
- {
- return newState == 0;
- }
- }
- }
- }
-
- private final CountSync control;
-
- public ReusableLatch()
- {
- this(0);
- }
-
- public ReusableLatch(final int count)
- {
- control = new CountSync(count);
- }
-
- public int getCount()
- {
- return control.getCount();
- }
-
- public void setCount(final int count)
- {
- control.setCount(count);
- }
-
- public void countUp()
- {
- control.add();
- }
-
- public void countDown()
- {
- control.releaseShared(1);
- }
-
-
- public void countDown(final int count)
- {
- control.releaseShared(count);
- }
-
- public void await() throws InterruptedException
- {
- control.acquireSharedInterruptibly(1);
- }
-
- public boolean await(final long milliseconds) throws InterruptedException
- {
- return control.tryAcquireSharedNanos(1, TimeUnit.MILLISECONDS.toNanos(milliseconds));
- }
-
- public boolean await(final long timeWait, TimeUnit timeUnit) throws InterruptedException
- {
- return control.tryAcquireSharedNanos(1, timeUnit.toNanos(timeWait));
- }
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/TypedProperties.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/TypedProperties.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/TypedProperties.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,1060 +0,0 @@
-/*
- * Copyright 2009 Red Hat, Inc.
- * Red Hat licenses this file to you under the Apache License, version
- * 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import static org.hornetq.utils.DataConstants.BOOLEAN;
-import static org.hornetq.utils.DataConstants.BYTE;
-import static org.hornetq.utils.DataConstants.BYTES;
-import static org.hornetq.utils.DataConstants.CHAR;
-import static org.hornetq.utils.DataConstants.DOUBLE;
-import static org.hornetq.utils.DataConstants.FLOAT;
-import static org.hornetq.utils.DataConstants.INT;
-import static org.hornetq.utils.DataConstants.LONG;
-import static org.hornetq.utils.DataConstants.NULL;
-import static org.hornetq.utils.DataConstants.SHORT;
-import static org.hornetq.utils.DataConstants.STRING;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import org.hornetq.api.core.HornetQBuffer;
-import org.hornetq.api.core.PropertyConversionException;
-import org.hornetq.api.core.SimpleString;
-import org.hornetq.core.logging.Logger;
-
-/**
- *
- * Property Value Conversion.
- * <p>
- * This implementation follows section 3.5.4 of the <i>Java Message Service<i>
- * specification (Version 1.1 April 12, 2002).
- * <p>
- * TODO - should have typed property getters and do conversions herein
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
- * @see <i>Java Message Service<i> specification (Version 1.1 April 12, 2002), section 3.5.4.
- */
-public class TypedProperties
-{
- private static final Logger log = Logger.getLogger(TypedProperties.class);
-
- private static final SimpleString HQ_PROPNAME = new SimpleString("_HQ_");
-
- private Map<SimpleString, PropertyValue> properties;
-
- private volatile int size;
-
- private boolean internalProperties;
-
- public TypedProperties()
- {
- }
-
- public int getMemoryOffset()
- {
- // The estimate is basically the encode size + 2 object references for each entry in the map
- // Note we don't include the attributes or anything else since they already included in the memory estimate
- // of the ServerMessage
-
- return properties == null ? 0 : size + 2 * DataConstants.SIZE_INT * properties.size();
- }
-
- public TypedProperties(final TypedProperties other)
- {
- properties = other.properties == null ? null : new HashMap<SimpleString, PropertyValue>(other.properties);
- size = other.size;
- }
-
- public boolean hasInternalProperties()
- {
- return internalProperties;
- }
-
- public void putBooleanProperty(final SimpleString key, final boolean value)
- {
- checkCreateProperties();
- doPutValue(key, new BooleanValue(value));
- }
-
- public void putByteProperty(final SimpleString key, final byte value)
- {
- checkCreateProperties();
- doPutValue(key, new ByteValue(value));
- }
-
- public void putBytesProperty(final SimpleString key, final byte[] value)
- {
- checkCreateProperties();
- doPutValue(key, value == null ? new NullValue() : new BytesValue(value));
- }
-
- public void putShortProperty(final SimpleString key, final short value)
- {
- checkCreateProperties();
- doPutValue(key, new ShortValue(value));
- }
-
- public void putIntProperty(final SimpleString key, final int value)
- {
- checkCreateProperties();
- doPutValue(key, new IntValue(value));
- }
-
- public void putLongProperty(final SimpleString key, final long value)
- {
- checkCreateProperties();
- doPutValue(key, new LongValue(value));
- }
-
- public void putFloatProperty(final SimpleString key, final float value)
- {
- checkCreateProperties();
- doPutValue(key, new FloatValue(value));
- }
-
- public void putDoubleProperty(final SimpleString key, final double value)
- {
- checkCreateProperties();
- doPutValue(key, new DoubleValue(value));
- }
-
- public void putSimpleStringProperty(final SimpleString key, final SimpleString value)
- {
- checkCreateProperties();
- doPutValue(key, value == null ? new NullValue() : new StringValue(value));
- }
-
- public void putCharProperty(final SimpleString key, final char value)
- {
- checkCreateProperties();
- doPutValue(key, new CharValue(value));
- }
-
- public void putTypedProperties(final TypedProperties otherProps)
- {
- if (otherProps == null || otherProps.properties == null)
- {
- return;
- }
-
- checkCreateProperties();
- Set<Entry<SimpleString, PropertyValue>> otherEntries = otherProps.properties.entrySet();
- for (Entry<SimpleString, PropertyValue> otherEntry : otherEntries)
- {
- doPutValue(otherEntry.getKey(), otherEntry.getValue());
- }
- }
-
- public Object getProperty(final SimpleString key)
- {
- return doGetProperty(key);
- }
-
- public Boolean getBooleanProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Boolean.valueOf(null);
- }
- else if (value instanceof Boolean)
- {
- return (Boolean)value;
- }
- else if (value instanceof SimpleString)
- {
- return Boolean.valueOf(((SimpleString)value).toString()).booleanValue();
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Byte getByteProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Byte.valueOf(null);
- }
- else if (value instanceof Byte)
- {
- return (Byte)value;
- }
- else if (value instanceof SimpleString)
- {
- return Byte.parseByte(((SimpleString)value).toString());
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Character getCharProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- throw new NullPointerException("Invalid conversion");
- }
-
- if (value instanceof Character)
- {
- return ((Character)value).charValue();
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public byte[] getBytesProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return null;
- }
- else if (value instanceof byte[])
- {
- return (byte[])value;
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Double getDoubleProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Double.valueOf(null);
- }
- else if (value instanceof Float)
- {
- return ((Float)value).doubleValue();
- }
- else if (value instanceof Double)
- {
- return (Double)value;
- }
- else if (value instanceof SimpleString)
- {
- return Double.parseDouble(((SimpleString)value).toString());
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Integer getIntProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Integer.valueOf(null);
- }
- else if (value instanceof Integer)
- {
- return (Integer)value;
- }
- else if (value instanceof Byte)
- {
- return ((Byte)value).intValue();
- }
- else if (value instanceof Short)
- {
- return ((Short)value).intValue();
- }
- else if (value instanceof SimpleString)
- {
- return Integer.parseInt(((SimpleString)value).toString());
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Long getLongProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Long.valueOf(null);
- }
- else if (value instanceof Long)
- {
- return (Long)value;
- }
- else if (value instanceof Byte)
- {
- return ((Byte)value).longValue();
- }
- else if (value instanceof Short)
- {
- return ((Short)value).longValue();
- }
- else if (value instanceof Integer)
- {
- return ((Integer)value).longValue();
- }
- else if (value instanceof SimpleString)
- {
- return Long.parseLong(((SimpleString)value).toString());
- }
- else
- {
- throw new PropertyConversionException("Invalid conversion");
- }
- }
-
- public Short getShortProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- {
- return Short.valueOf(null);
- }
- else if (value instanceof Byte)
- {
- return ((Byte)value).shortValue();
- }
- else if (value instanceof Short)
- {
- return (Short)value;
- }
- else if (value instanceof SimpleString)
- {
- return Short.parseShort(((SimpleString)value).toString());
- }
- else
- {
- throw new PropertyConversionException("Invalid Conversion.");
- }
- }
-
- public Float getFloatProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
- if (value == null)
- return Float.valueOf(null);
- if (value instanceof Float)
- {
- return ((Float)value).floatValue();
- }
- if (value instanceof SimpleString)
- {
- return Float.parseFloat(((SimpleString)value).toString());
- }
- throw new PropertyConversionException("Invalid conversion: " + key);
- }
-
- public SimpleString getSimpleStringProperty(final SimpleString key) throws PropertyConversionException
- {
- Object value = doGetProperty(key);
-
- if (value == null)
- {
- return null;
- }
-
- if (value instanceof SimpleString)
- {
- return (SimpleString)value;
- }
- else if (value instanceof Boolean)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Character)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Byte)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Short)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Integer)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Long)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Float)
- {
- return new SimpleString(value.toString());
- }
- else if (value instanceof Double)
- {
- return new SimpleString(value.toString());
- }
- throw new PropertyConversionException("Invalid conversion");
- }
-
- public Object removeProperty(final SimpleString key)
- {
- return doRemoveProperty(key);
- }
-
- public boolean containsProperty(final SimpleString key)
- {
- if (size == 0)
- {
- return false;
-
- }
- else
- {
- return properties.containsKey(key);
- }
- }
-
- public Set<SimpleString> getPropertyNames()
- {
- if (size == 0)
- {
- return Collections.emptySet();
- }
- else
- {
- return properties.keySet();
- }
- }
-
- public synchronized void decode(final HornetQBuffer buffer)
- {
- byte b = buffer.readByte();
-
- if (b == DataConstants.NULL)
- {
- properties = null;
- }
- else
- {
- int numHeaders = buffer.readInt();
-
- properties = new HashMap<SimpleString, PropertyValue>(numHeaders);
- size = 0;
-
- for (int i = 0; i < numHeaders; i++)
- {
- int len = buffer.readInt();
- byte[] data = new byte[len];
- buffer.readBytes(data);
- SimpleString key = new SimpleString(data);
-
- byte type = buffer.readByte();
-
- PropertyValue val;
-
- switch (type)
- {
- case NULL:
- {
- val = new NullValue();
- doPutValue(key, val);
- break;
- }
- case CHAR:
- {
- val = new CharValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BOOLEAN:
- {
- val = new BooleanValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BYTE:
- {
- val = new ByteValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BYTES:
- {
- val = new BytesValue(buffer);
- doPutValue(key, val);
- break;
- }
- case SHORT:
- {
- val = new ShortValue(buffer);
- doPutValue(key, val);
- break;
- }
- case INT:
- {
- val = new IntValue(buffer);
- doPutValue(key, val);
- break;
- }
- case LONG:
- {
- val = new LongValue(buffer);
- doPutValue(key, val);
- break;
- }
- case FLOAT:
- {
- val = new FloatValue(buffer);
- doPutValue(key, val);
- break;
- }
- case DOUBLE:
- {
- val = new DoubleValue(buffer);
- doPutValue(key, val);
- break;
- }
- case STRING:
- {
- val = new StringValue(buffer);
- doPutValue(key, val);
- break;
- }
- default:
- {
- throw new IllegalArgumentException("Invalid type: " + type);
- }
- }
- }
- }
- }
-
- public synchronized void encode(final HornetQBuffer buffer)
- {
- if (properties == null)
- {
- buffer.writeByte(DataConstants.NULL);
- }
- else
- {
- buffer.writeByte(DataConstants.NOT_NULL);
-
- buffer.writeInt(properties.size());
-
- for (Map.Entry<SimpleString, PropertyValue> entry : properties.entrySet())
- {
- SimpleString s = entry.getKey();
- byte[] data = s.getData();
- buffer.writeInt(data.length);
- buffer.writeBytes(data);
-
- entry.getValue().write(buffer);
- }
- }
- }
-
- public int getEncodeSize()
- {
- if (properties == null)
- {
- return DataConstants.SIZE_BYTE;
- }
- else
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size;
- }
- }
-
- public void clear()
- {
- if (properties != null)
- {
- properties.clear();
- }
- }
-
- @Override
- public String toString()
- {
- return "TypedProperties[" + properties + "]";
- }
-
- // Private ------------------------------------------------------------------------------------
-
- private void checkCreateProperties()
- {
- if (properties == null)
- {
- properties = new HashMap<SimpleString, PropertyValue>();
- }
- }
-
- private synchronized void doPutValue(final SimpleString key, final PropertyValue value)
- {
- if (key.startsWith(HQ_PROPNAME))
- {
- internalProperties = true;
- }
-
- PropertyValue oldValue = properties.put(key, value);
- if (oldValue != null)
- {
- size += value.encodeSize() - oldValue.encodeSize();
- }
- else
- {
- size += SimpleString.sizeofString(key) + value.encodeSize();
- }
- }
-
- private synchronized Object doRemoveProperty(final SimpleString key)
- {
- if (properties == null)
- {
- return null;
- }
-
- PropertyValue val = properties.remove(key);
-
- if (val == null)
- {
- return null;
- }
- else
- {
- size -= SimpleString.sizeofString(key) + val.encodeSize();
-
- return val.getValue();
- }
- }
-
- private synchronized Object doGetProperty(final Object key)
- {
- if (size == 0)
- {
- return null;
- }
-
- PropertyValue val = properties.get(key);
-
- if (val == null)
- {
- return null;
- }
- else
- {
- return val.getValue();
- }
- }
-
- // Inner classes ------------------------------------------------------------------------------
-
- private static abstract class PropertyValue
- {
- abstract Object getValue();
-
- abstract void write(HornetQBuffer buffer);
-
- abstract int encodeSize();
-
- @Override
- public String toString()
- {
- return "" + getValue();
- }
- }
-
- private static final class NullValue extends PropertyValue
- {
- public NullValue()
- {
- }
-
- @Override
- public Object getValue()
- {
- return null;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.NULL);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE;
- }
-
- }
-
- private static final class BooleanValue extends PropertyValue
- {
- final boolean val;
-
- public BooleanValue(final boolean val)
- {
- this.val = val;
- }
-
- public BooleanValue(final HornetQBuffer buffer)
- {
- val = buffer.readBoolean();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.BOOLEAN);
- buffer.writeBoolean(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN;
- }
-
- }
-
- private static final class ByteValue extends PropertyValue
- {
- final byte val;
-
- public ByteValue(final byte val)
- {
- this.val = val;
- }
-
- public ByteValue(final HornetQBuffer buffer)
- {
- val = buffer.readByte();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.BYTE);
- buffer.writeByte(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_BYTE;
- }
- }
-
- private static final class BytesValue extends PropertyValue
- {
- final byte[] val;
-
- public BytesValue(final byte[] val)
- {
- this.val = val;
- }
-
- public BytesValue(final HornetQBuffer buffer)
- {
- int len = buffer.readInt();
- val = new byte[len];
- buffer.readBytes(val);
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.BYTES);
- buffer.writeInt(val.length);
- buffer.writeBytes(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + val.length;
- }
-
- }
-
- private static final class ShortValue extends PropertyValue
- {
- final short val;
-
- public ShortValue(final short val)
- {
- this.val = val;
- }
-
- public ShortValue(final HornetQBuffer buffer)
- {
- val = buffer.readShort();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.SHORT);
- buffer.writeShort(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_SHORT;
- }
- }
-
- private static final class IntValue extends PropertyValue
- {
- final int val;
-
- public IntValue(final int val)
- {
- this.val = val;
- }
-
- public IntValue(final HornetQBuffer buffer)
- {
- val = buffer.readInt();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.INT);
- buffer.writeInt(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
- }
- }
-
- private static final class LongValue extends PropertyValue
- {
- final long val;
-
- public LongValue(final long val)
- {
- this.val = val;
- }
-
- public LongValue(final HornetQBuffer buffer)
- {
- val = buffer.readLong();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.LONG);
- buffer.writeLong(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
- }
- }
-
- private static final class FloatValue extends PropertyValue
- {
- final float val;
-
- public FloatValue(final float val)
- {
- this.val = val;
- }
-
- public FloatValue(final HornetQBuffer buffer)
- {
- val = Float.intBitsToFloat(buffer.readInt());
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.FLOAT);
- buffer.writeInt(Float.floatToIntBits(val));
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_FLOAT;
- }
-
- }
-
- private static final class DoubleValue extends PropertyValue
- {
- final double val;
-
- public DoubleValue(final double val)
- {
- this.val = val;
- }
-
- public DoubleValue(final HornetQBuffer buffer)
- {
- val = Double.longBitsToDouble(buffer.readLong());
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.DOUBLE);
- buffer.writeLong(Double.doubleToLongBits(val));
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_DOUBLE;
- }
- }
-
- private static final class CharValue extends PropertyValue
- {
- final char val;
-
- public CharValue(final char val)
- {
- this.val = val;
- }
-
- public CharValue(final HornetQBuffer buffer)
- {
- val = (char)buffer.readShort();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.CHAR);
- buffer.writeShort((short)val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_CHAR;
- }
- }
-
- private static final class StringValue extends PropertyValue
- {
- final SimpleString val;
-
- public StringValue(final SimpleString val)
- {
- this.val = val;
- }
-
- public StringValue(final HornetQBuffer buffer)
- {
- val = buffer.readSimpleString();
- }
-
- @Override
- public Object getValue()
- {
- return val;
- }
-
- @Override
- public void write(final HornetQBuffer buffer)
- {
- buffer.writeByte(DataConstants.STRING);
- buffer.writeSimpleString(val);
- }
-
- @Override
- public int encodeSize()
- {
- return DataConstants.SIZE_BYTE + SimpleString.sizeofString(val);
- }
- }
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/UUID.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/UUID.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/UUID.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,236 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
- *
- * Licensed under the License specified in the file licenses/LICENSE.txt which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hornetq.utils;
-
-/**
- * UUID represents Universally Unique Identifiers (aka Global UID in Windows
- * world). UUIDs are usually generated via UUIDGenerator (or in case of 'Null
- * UUID', 16 zero bytes, via static method getNullUUID()), or received from
- * external systems.
- *
- * By default class caches the string presentations of UUIDs so that description
- * is only created the first time it's needed. For memory stingy applications
- * this caching can be turned off (note though that if uuid.toString() is never
- * called, desc is never calculated so only loss is the space allocated for the
- * desc pointer... which can of course be commented out to save memory).
- *
- * Similarly, hash code is calculated when it's needed for the first time, and
- * from thereon that value is just returned. This means that using UUIDs as keys
- * should be reasonably efficient.
- *
- * UUIDs can be compared for equality, serialized, cloned and even sorted.
- * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by
- * first ordering based on type (in the order of numeric values of types),
- * secondarily by time stamp (only for time-based time stamps), and finally by
- * straight numeric byte-by-byte comparison (from most to least significant
- * bytes).
- */
-
-public final class UUID
-{
- private final static String kHexChars = "0123456789abcdefABCDEF";
-
- public final static byte INDEX_CLOCK_HI = 6;
-
- public final static byte INDEX_CLOCK_MID = 4;
-
- public final static byte INDEX_CLOCK_LO = 0;
-
- public final static byte INDEX_TYPE = 6;
-
- // Clock seq. & variant are multiplexed...
- public final static byte INDEX_CLOCK_SEQUENCE = 8;
-
- public final static byte INDEX_VARIATION = 8;
-
- public final static byte TYPE_NULL = 0;
-
- public final static byte TYPE_TIME_BASED = 1;
-
- public final static byte TYPE_DCE = 2; // Not used
-
- public final static byte TYPE_NAME_BASED = 3;
-
- public final static byte TYPE_RANDOM_BASED = 4;
-
- /*
- * 'Standard' namespaces defined (suggested) by UUID specs:
- */
- public final static String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
-
- public final static String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
-
- public final static String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
-
- public final static String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
-
- /*
- * By default let's cache desc, can be turned off. For hash code there's no
- * point in turning it off (since the int is already part of the instance
- * memory allocation); if you want to save those 4 bytes (or possibly bit
- * more if alignment is bad) just comment out hash caching.
- */
- private static boolean sDescCaching = true;
-
- private final byte[] mId;
-
- // Both string presentation and hash value may be cached...
- private transient String mDesc = null;
-
- private transient int mHashCode = 0;
-
- /**
- *
- *
- * @param type
- * UUID type
- * @param data
- * 16 byte UUID contents
- */
- public UUID(final int type, final byte[] data)
- {
- mId = data;
- // Type is multiplexed with time_hi:
- mId[UUID.INDEX_TYPE] &= (byte)0x0F;
- mId[UUID.INDEX_TYPE] |= (byte)(type << 4);
- // Variant masks first two bits of the clock_seq_hi:
- mId[UUID.INDEX_VARIATION] &= (byte)0x3F;
- mId[UUID.INDEX_VARIATION] |= (byte)0x80;
- }
-
- public final byte[] asBytes()
- {
- return mId;
- }
-
- /**
- * Could use just the default hash code, but we can probably create a better
- * identity hash (ie. same contents generate same hash) manually, without
- * sacrificing speed too much. Although multiplications with modulos would
- * generate better hashing, let's use just shifts, and do 2 bytes at a time.
- * <p>
- * Of course, assuming UUIDs are randomized enough, even simpler approach
- * might be good enough?
- * <p>
- * Is this a good hash? ... one of these days I better read more about basic
- * hashing techniques I swear!
- */
- private final static int[] kShifts = { 3, 7, 17, 21, 29, 4, 9 };
-
- @Override
- public final int hashCode()
- {
- if (mHashCode == 0)
- {
- // Let's handle first and last byte separately:
- int result = mId[0] & 0xFF;
-
- result |= result << 16;
- result |= result << 8;
-
- for (int i = 1; i < 15; i += 2)
- {
- int curr = (mId[i] & 0xFF) << 8 | mId[i + 1] & 0xFF;
- int shift = UUID.kShifts[i >> 1];
-
- if (shift > 16)
- {
- result ^= curr << shift | curr >>> 32 - shift;
- }
- else
- {
- result ^= curr << shift;
- }
- }
-
- // and then the last byte:
- int last = mId[15] & 0xFF;
- result ^= last << 3;
- result ^= last << 13;
-
- result ^= last << 27;
- // Let's not accept hash 0 as it indicates 'not hashed yet':
- if (result == 0)
- {
- mHashCode = -1;
- }
- else
- {
- mHashCode = result;
- }
- }
- return mHashCode;
- }
-
- @Override
- public final String toString()
- {
- /*
- * Could be synchronized, but there isn't much harm in just taking our
- * chances (ie. in the worst case we'll form the string more than once...
- * but result is the same)
- */
-
- if (mDesc == null)
- {
- StringBuffer b = new StringBuffer(36);
-
- for (int i = 0; i < 16; ++i)
- {
- // Need to bypass hyphens:
- switch (i)
- {
- case 4:
- case 6:
- case 8:
- case 10:
- b.append('-');
- }
- int hex = mId[i] & 0xFF;
- b.append(UUID.kHexChars.charAt(hex >> 4));
- b.append(UUID.kHexChars.charAt(hex & 0x0f));
- }
- if (!UUID.sDescCaching)
- {
- return b.toString();
- }
- mDesc = b.toString();
- }
- return mDesc;
- }
-
- /**
- * Checking equality of UUIDs is easy; just compare the 128-bit number.
- */
- @Override
- public final boolean equals(final Object o)
- {
- if (!(o instanceof UUID))
- {
- return false;
- }
- byte[] otherId = ((UUID)o).mId;
- byte[] thisId = mId;
- for (int i = 0; i < 16; ++i)
- {
- if (otherId[i] != thisId[i])
- {
- return false;
- }
- }
- return true;
- }
-}
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDGenerator.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDGenerator.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDGenerator.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,293 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
- *
- * Licensed under the License specified in the file licenses/LICENSE.txt which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import java.lang.reflect.Method;
-import java.net.NetworkInterface;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.Random;
-
-import org.hornetq.api.core.SimpleString;
-import org.hornetq.core.logging.Logger;
-
-public final class UUIDGenerator
-{
- private final static UUIDGenerator sSingleton = new UUIDGenerator();
-
- private static final Logger log = Logger.getLogger(UUIDGenerator.class);
-
- // Windows has some fake adapters that will return the same HARDWARE ADDRESS on any computer. We need to ignore those
- private static final byte[][] BLACK_LIST = new byte[][] { { 2, 0, 84, 85, 78, 1 } };
-
- /**
- * Random-generator, used by various UUID-generation methods:
- */
- private Random mRnd = null;
-
- private final Object mTimerLock = new Object();
-
- private UUIDTimer mTimer = null;
-
- private byte[] address;
-
- /**
- * Constructor is private to enforce singleton access.
- */
- private UUIDGenerator()
- {
- }
-
- /**
- * Method used for accessing the singleton generator instance.
- */
- public static UUIDGenerator getInstance()
- {
- return UUIDGenerator.sSingleton;
- }
-
- /*
- * ///////////////////////////////////////////////////// // Configuration
- * /////////////////////////////////////////////////////
- */
-
- /**
- * Method for getting the shared random number generator used for generating
- * the UUIDs. This way the initialization cost is only taken once; access
- * need not be synchronized (or in cases where it has to, SecureRandom takes
- * care of it); it might even be good for getting really 'random' stuff to
- * get shared access...
- */
- public final Random getRandomNumberGenerator()
- {
- /*
- * Could be synchronized, but since side effects are trivial (ie.
- * possibility of generating more than one SecureRandom, of which all but
- * one are dumped) let's not add synchronization overhead:
- */
- if (mRnd == null)
- {
- mRnd = new SecureRandom();
- }
- return mRnd;
- }
-
- public final UUID generateTimeBasedUUID(final byte[] byteAddr)
- {
- byte[] contents = new byte[16];
- int pos = 10;
- for (int i = 0; i < 6; ++i)
- {
- contents[pos + i] = byteAddr[i];
- }
-
- synchronized (mTimerLock)
- {
- if (mTimer == null)
- {
- mTimer = new UUIDTimer(getRandomNumberGenerator());
- }
-
- mTimer.getTimestamp(contents);
- }
-
- return new UUID(UUID.TYPE_TIME_BASED, contents);
- }
-
- public final byte[] generateDummyAddress()
- {
- Random rnd = getRandomNumberGenerator();
- byte[] dummy = new byte[6];
- rnd.nextBytes(dummy);
- /* Need to set the broadcast bit to indicate it's not a real
- * address.
- */
- dummy[0] |= (byte)0x01;
-
- if (UUIDGenerator.log.isDebugEnabled())
- {
- UUIDGenerator.log.debug("using dummy address " + UUIDGenerator.asString(dummy));
- }
- return dummy;
- }
-
- /**
- * If running java 6 or above, returns {@link NetworkInterface#getHardwareAddress()}, else return <code>null</code>.
- * The first hardware address is returned when iterating all the NetworkInterfaces
- */
- public final static byte[] getHardwareAddress()
- {
- Method getHardwareAddressMethod;
- Method isUpMethod;
- Method isLoopbackMethod;
- Method isVirtualMethod;
- try
- {
- getHardwareAddressMethod = NetworkInterface.class.getMethod("getHardwareAddress");
- isUpMethod = NetworkInterface.class.getMethod("isUp");
- isLoopbackMethod = NetworkInterface.class.getMethod("isLoopback");
- isVirtualMethod = NetworkInterface.class.getMethod("isVirtual");
- }
- catch (Throwable t)
- {
- // not on Java 6 or not enough security permission
- return null;
- }
-
- try
- {
- Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
- while (networkInterfaces.hasMoreElements())
- {
- NetworkInterface networkInterface = networkInterfaces.nextElement();
- boolean up = (Boolean)isUpMethod.invoke(networkInterface);
- boolean loopback = (Boolean)isLoopbackMethod.invoke(networkInterface);
- boolean virtual = (Boolean)isVirtualMethod.invoke(networkInterface);
-
- if (loopback || virtual || !up)
- {
- continue;
- }
-
- Object res = getHardwareAddressMethod.invoke(networkInterface);
- if (res != null && res instanceof byte[])
- {
- byte[] address = (byte[])res;
- byte[] paddedAddress = UUIDGenerator.getZeroPaddedSixBytes(address);
-
- if (UUIDGenerator.isBlackList(address))
- {
- continue;
- }
-
- if (paddedAddress != null)
- {
- if (UUIDGenerator.log.isDebugEnabled())
- {
- UUIDGenerator.log.debug("using hardware address " + UUIDGenerator.asString(paddedAddress));
- }
- return paddedAddress;
- }
- }
- }
- }
- catch (Throwable t)
- {
- }
-
- return null;
- }
-
- public final SimpleString generateSimpleStringUUID()
- {
- return new SimpleString(generateStringUUID());
- }
-
- public final UUID generateUUID()
- {
- byte[] address = getAddressBytes();
-
- UUID uid = generateTimeBasedUUID(address);
-
- return uid;
- }
-
- public final String generateStringUUID()
- {
- byte[] address = getAddressBytes();
-
- if (address == null)
- {
- return java.util.UUID.randomUUID().toString();
- }
- else
- {
- return generateTimeBasedUUID(address).toString();
- }
- }
-
- public final static byte[] getZeroPaddedSixBytes(final byte[] bytes)
- {
- if (bytes == null)
- {
- return null;
- }
- if (bytes.length > 0 && bytes.length <= 6)
- {
- if (bytes.length == 6)
- {
- return bytes;
- }
- else
- {
- // pad with zeroes to have a 6-byte array
- byte[] paddedAddress = new byte[6];
- System.arraycopy(bytes, 0, paddedAddress, 0, bytes.length);
- for (int i = bytes.length; i < 6; i++)
- {
- paddedAddress[i] = 0;
- }
- return paddedAddress;
- }
- }
- return null;
- }
-
- // Private -------------------------------------------------------
-
- private static final boolean isBlackList(final byte[] address)
- {
- for (byte[] blackList : UUIDGenerator.BLACK_LIST)
- {
- if (Arrays.equals(address, blackList))
- {
- return true;
- }
- }
- return false;
- }
-
- private final byte[] getAddressBytes()
- {
- if (address == null)
- {
- address = UUIDGenerator.getHardwareAddress();
- if (address == null)
- {
- address = generateDummyAddress();
- }
- }
-
- return address;
- }
-
- private static final String asString(final byte[] bytes)
- {
- if (bytes == null)
- {
- return null;
- }
-
- String s = "";
- for (int i = 0; i < bytes.length - 1; i++)
- {
- s += Integer.toHexString(bytes[i]) + ":";
- }
- s += bytes[bytes.length - 1];
- return s;
- }
-}
\ No newline at end of file
Deleted: trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDTimer.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDTimer.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-core/src/main/java/org/hornetq/utils/UUIDTimer.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -1,326 +0,0 @@
-/* JUG Java Uuid Generator
- *
- * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
- *
- * Licensed under the License specified in the file licenses/LICENSE.txt which is
- * included with the source code.
- * You may not use this file except in compliance with the License.
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hornetq.utils;
-
-import java.util.Random;
-
-/**
- * UUIDTimer produces the time stamps required for time-based UUIDs. It works as
- * outlined in the UUID specification, with following implementation:
- * <ul>
- * <li>Java classes can only product time stamps with maximum resolution of one
- * millisecond (at least before JDK 1.5). To compensate, an additional counter
- * is used, so that more than one UUID can be generated between java clock
- * updates. Counter may be used to generate up to 10000 UUIDs for each distrinct
- * java clock value.
- * <li>Due to even lower clock resolution on some platforms (older Windows
- * versions use 55 msec resolution), timestamp value can also advanced ahead of
- * physical value within limits (by default, up 100 millisecond ahead of
- * reported), iff necessary (ie. 10000 instances created before clock time
- * advances).
- * <li>As an additional precaution, counter is initialized not to 0 but to a
- * random 8-bit number, and each time clock changes, lowest 8-bits of counter
- * are preserved. The purpose it to make likelyhood of multi-JVM multi-instance
- * generators to collide, without significantly reducing max. UUID generation
- * speed. Note though that using more than one generator (from separate JVMs) is
- * strongly discouraged, so hopefully this enhancement isn't needed. This 8-bit
- * offset has to be reduced from total max. UUID count to preserve ordering
- * property of UUIDs (ie. one can see which UUID was generated first for given
- * UUID generator); the resulting 9500 UUIDs isn't much different from the
- * optimal choice.
- * <li>Finally, as of version 2.0 and onwards, optional external timestamp
- * synchronization can be done. This is done similar to the way UUID
- * specification suggests; except that since there is no way to lock the whole
- * system, file-based locking is used. This works between multiple JVMs and Jug
- * instances.
- * </ul>
- * <p>
- * Some additional assumptions about calculating the timestamp:
- * <ul>
- * <li>System.currentTimeMillis() is assumed to give time offset in UTC, or at
- * least close enough thing to get correct timestamps. The alternate route would
- * have to go through calendar object, use TimeZone offset to get to UTC, and
- * then modify. Using currentTimeMillis should be much faster to allow rapid
- * UUID creation.
- * <li>Similarly, the constant used for time offset between 1.1.1970 and start
- * of Gregorian calendar is assumed to be correct (which seems to be the case
- * when testing with Java calendars).
- * </ul>
- * <p>
- * Note about synchronization: this class is assumed to always be called from a
- * synchronized context (caller locks on either this object, or a similar timer
- * lock), and so has no method synchronization.
- */
-public class UUIDTimer
-{
- // // // Constants
-
- /**
- * Since System.longTimeMillis() returns time from january 1st 1970, and
- * UUIDs need time from the beginning of gregorian calendar (15-oct-1582),
- * need to apply the offset:
- */
- private final static long kClockOffset = 0x01b21dd213814000L;
-
- /**
- * Also, instead of getting time in units of 100nsecs, we get something with
- * max resolution of 1 msec... and need the multiplier as well
- */
- private final static long kClockMultiplier = 10000;
-
- private final static long kClockMultiplierL = 10000L;
-
- /**
- * Let's allow "virtual" system time to advance at most 100 milliseconds
- * beyond actual physical system time, before adding delays.
- */
- private final static long kMaxClockAdvance = 100L;
-
- // // // Configuration
-
- private final Random mRnd;
-
- // // // Clock state:
-
- /**
- * Additional state information used to protect against anomalous cases
- * (clock time going backwards, node id getting mixed up). Third byte is
- * actually used for seeding counter on counter overflow.
- */
- private final byte[] mClockSequence = new byte[3];
-
- /**
- * Last physical timestamp value <code>System.currentTimeMillis()</code>
- * returned: used to catch (and report) cases where system clock goes
- * backwards. Is also used to limit "drifting", that is, amount timestamps
- * used can differ from the system time value. This value is not guaranteed
- * to be monotonically increasing.
- */
- private long mLastSystemTimestamp = 0L;
-
- /**
- * Timestamp value last used for generating a UUID (along with
- * {@link #mClockCounter}. Usually the same as {@link #mLastSystemTimestamp},
- * but not always (system clock moved backwards). Note that this value is
- * guaranteed to be monotonically increasing; that is, at given absolute time
- * points t1 and t2 (where t2 is after t1), t1 <= t2 will always hold true.
- */
- private long mLastUsedTimestamp = 0L;
-
- /**
- * Counter used to compensate inadequate resolution of JDK system timer.
- */
- private int mClockCounter = 0;
-
- UUIDTimer(final Random rnd)
- {
- mRnd = rnd;
- initCounters(rnd);
- mLastSystemTimestamp = 0L;
- // This may get overwritten by the synchronizer
- mLastUsedTimestamp = 0L;
- }
-
- private void initCounters(final Random rnd)
- {
- /*
- * Let's generate the clock sequence field now; as with counter, this
- * reduces likelihood of collisions (as explained in UUID specs)
- */
- rnd.nextBytes(mClockSequence);
- /*
- * Ok, let's also initialize the counter... Counter is used to make it
- * slightly less likely that two instances of UUIDGenerator (from separate
- * JVMs as no more than one can be created in one JVM) would produce
- * colliding time-based UUIDs. The practice of using multiple generators,
- * is strongly discouraged, of course, but just in case...
- */
- mClockCounter = mClockSequence[2] & 0xFF;
- }
-
- public void getTimestamp(final byte[] uuidData)
- {
- // First the clock sequence:
- uuidData[UUID.INDEX_CLOCK_SEQUENCE] = mClockSequence[0];
- uuidData[UUID.INDEX_CLOCK_SEQUENCE + 1] = mClockSequence[1];
-
- long systime = System.currentTimeMillis();
-
- /*
- * Let's first verify that the system time is not going backwards;
- * independent of whether we can use it:
- */
- if (systime < mLastSystemTimestamp)
- {
- // Logger.logWarning("System time going backwards! (got value
- // "+systime+", last "+mLastSystemTimestamp);
- // Let's write it down, still
- mLastSystemTimestamp = systime;
- }
-
- /*
- * But even without it going backwards, it may be less than the last one
- * used (when generating UUIDs fast with coarse clock resolution; or if
- * clock has gone backwards over reboot etc).
- */
- if (systime <= mLastUsedTimestamp)
- {
- /*
- * Can we just use the last time stamp (ok if the counter hasn't hit
- * max yet)
- */
- if (mClockCounter < UUIDTimer.kClockMultiplier)
- { // yup, still have room
- systime = mLastUsedTimestamp;
- }
- else
- { // nope, have to roll over to next value and maybe wait
- long actDiff = mLastUsedTimestamp - systime;
- long origTime = systime;
- systime = mLastUsedTimestamp + 1L;
-
- // Logger.logWarning("Timestamp over-run: need to reinitialize
- // random sequence");
-
- /*
- * Clock counter is now at exactly the multiplier; no use just
- * anding its value. So, we better get some random numbers
- * instead...
- */
- initCounters(mRnd);
-
- /*
- * But do we also need to slow down? (to try to keep virtual time
- * close to physical time; ie. either catch up when system clock has
- * been moved backwards, or when coarse clock resolution has forced
- * us to advance virtual timer too far)
- */
- if (actDiff >= UUIDTimer.kMaxClockAdvance)
- {
- UUIDTimer.slowDown(origTime, actDiff);
- }
- }
- }
- else
- {
- /*
- * Clock has advanced normally; just need to make sure counter is reset
- * to a low value (need not be 0; good to leave a small residual to
- * further decrease collisions)
- */
- mClockCounter &= 0xFF;
- }
-
- mLastUsedTimestamp = systime;
-
- /*
- * Now, let's translate the timestamp to one UUID needs, 100ns unit offset
- * from the beginning of Gregorian calendar...
- */
- systime *= UUIDTimer.kClockMultiplierL;
- systime += UUIDTimer.kClockOffset;
-
- // Plus add the clock counter:
- systime += mClockCounter;
- // and then increase
- ++mClockCounter;
-
- /*
- * Time fields are nicely split across the UUID, so can't just linearly
- * dump the stamp:
- */
- int clockHi = (int)(systime >>> 32);
- int clockLo = (int)systime;
-
- uuidData[UUID.INDEX_CLOCK_HI] = (byte)(clockHi >>> 24);
- uuidData[UUID.INDEX_CLOCK_HI + 1] = (byte)(clockHi >>> 16);
- uuidData[UUID.INDEX_CLOCK_MID] = (byte)(clockHi >>> 8);
- uuidData[UUID.INDEX_CLOCK_MID + 1] = (byte)clockHi;
-
- uuidData[UUID.INDEX_CLOCK_LO] = (byte)(clockLo >>> 24);
- uuidData[UUID.INDEX_CLOCK_LO + 1] = (byte)(clockLo >>> 16);
- uuidData[UUID.INDEX_CLOCK_LO + 2] = (byte)(clockLo >>> 8);
- uuidData[UUID.INDEX_CLOCK_LO + 3] = (byte)clockLo;
- }
-
- /*
- * /////////////////////////////////////////////////////////// // Private
- * methods ///////////////////////////////////////////////////////////
- */
-
- private final static int MAX_WAIT_COUNT = 50;
-
- /**
- * Simple utility method to use to wait for couple of milliseconds, to let
- * system clock hopefully advance closer to the virtual timestamps used.
- * Delay is kept to just a millisecond or two, to prevent excessive blocking;
- * but that should be enough to eventually synchronize physical clock with
- * virtual clock values used for UUIDs.
- *
- * @param msecs
- * Number of milliseconds to wait for from current time point
- */
- private final static void slowDown(final long startTime, final long actDiff)
- {
- /*
- * First, let's determine how long we'd like to wait. This is based on how
- * far ahead are we as of now.
- */
- long ratio = actDiff / UUIDTimer.kMaxClockAdvance;
- long delay;
-
- if (ratio < 2L)
- { // 200 msecs or less
- delay = 1L;
- }
- else if (ratio < 10L)
- { // 1 second or less
- delay = 2L;
- }
- else if (ratio < 600L)
- { // 1 minute or less
- delay = 3L;
- }
- else
- {
- delay = 5L;
- }
- // Logger.logWarning("Need to wait for "+delay+" milliseconds; virtual
- // clock advanced too far in the future");
- long waitUntil = startTime + delay;
- int counter = 0;
- do
- {
- try
- {
- Thread.sleep(delay);
- }
- catch (InterruptedException ie)
- {
- }
- delay = 1L;
- /*
- * This is just a sanity check: don't want an "infinite" loop if clock
- * happened to be moved backwards by, say, an hour...
- */
- if (++counter > UUIDTimer.MAX_WAIT_COUNT)
- {
- break;
- }
- }
- while (System.currentTimeMillis() < waitUntil);
- }
-}
Added: trunk/hornetq-journal/pom.xml
===================================================================
--- trunk/hornetq-journal/pom.xml (rev 0)
+++ trunk/hornetq-journal/pom.xml 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,65 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.hornetq</groupId>
+ <artifactId>hornetq-pom</artifactId>
+ <version>2.2.3-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>hornetq-journal</artifactId>
+ <packaging>jar</packaging>
+ <name>HornetQ Journal</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hornetq</groupId>
+ <artifactId>hornetq-commons</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8</version>
+ <configuration>
+ <doclet>org.jboss.apiviz.APIviz</doclet>
+ <docletArtifact>
+ <groupId>org.jboss.apiviz</groupId>
+ <artifactId>apiviz</artifactId>
+ <version>1.3.1.GA</version>
+ </docletArtifact>
+ <useStandardDocletOptions>true</useStandardDocletOptions>
+ <minmemory>128m</minmemory>
+ <maxmemory>512m</maxmemory>
+ <quiet>false</quiet>
+ <aggregate>true</aggregate>
+ <excludePackageNames>org.hornetq.core:org.hornetq.utils</excludePackageNames>
+ </configuration>
+ <executions>
+ <execution>
+ <id>javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
Modified: trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AIOSequentialFileFactory.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/core/journal/impl/AIOSequentialFileFactory.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AIOSequentialFileFactory.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -14,8 +14,6 @@
package org.hornetq.core.journal.impl;
import java.nio.ByteBuffer;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -23,16 +21,14 @@
import org.hornetq.core.asyncio.BufferCallback;
import org.hornetq.core.asyncio.impl.AsynchronousFileImpl;
-import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
-import org.hornetq.core.config.impl.ConfigurationImpl;
import org.hornetq.core.journal.SequentialFile;
import org.hornetq.core.logging.Logger;
import org.hornetq.utils.HornetQThreadFactory;
/**
- *
+ *
* A AIOSequentialFileFactory
- *
+ *
* @author clebert.suconic at jboss.com
*
*/
@@ -58,8 +54,8 @@
public AIOSequentialFileFactory(final String journalDir)
{
this(journalDir,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_SIZE_AIO,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_TIMEOUT_AIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_SIZE_AIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_TIMEOUT_AIO,
false);
}
@@ -147,7 +143,7 @@
pollerExecutor = Executors.newCachedThreadPool(new HornetQThreadFactory("HornetQ-AIO-poller-pool" + System.identityHashCode(this),
true,
- AIOSequentialFileFactory.getThisClassLoader()));
+ AbstractSequentialFileFactory.getThisClassLoader()));
}
@@ -296,17 +292,4 @@
}
}
}
-
- private static ClassLoader getThisClassLoader()
- {
- return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
- {
- public ClassLoader run()
- {
- return ClientSessionFactoryImpl.class.getClassLoader();
- }
- });
-
- }
-
}
Modified: trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AbstractSequentialFileFactory.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/core/journal/impl/AbstractSequentialFileFactory.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/AbstractSequentialFileFactory.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -25,16 +25,15 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
import org.hornetq.core.journal.SequentialFile;
import org.hornetq.core.journal.SequentialFileFactory;
import org.hornetq.core.logging.Logger;
import org.hornetq.utils.HornetQThreadFactory;
/**
- *
+ *
* An abstract SequentialFileFactory containing basic functionality for both AIO and NIO SequentialFactories
- *
+ *
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
* @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
*
@@ -55,7 +54,7 @@
protected final long bufferTimeout;
- /**
+ /**
* Asynchronous writes need to be done at another executor.
* This needs to be done at NIO, or else we would have the callers thread blocking for the return.
* At AIO this is necessary as context switches on writes would fire flushes at the kernel.
@@ -156,7 +155,7 @@
{
}
- /**
+ /**
* Create the directory if it doesn't exist yet
*/
public void createDirs() throws Exception
@@ -191,13 +190,13 @@
return Arrays.asList(fileNames);
}
- private static ClassLoader getThisClassLoader()
+ protected static ClassLoader getThisClassLoader()
{
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
{
public ClassLoader run()
{
- return ClientSessionFactoryImpl.class.getClassLoader();
+ return AbstractSequentialFileFactory.class.getClassLoader(); // XXX FIXME!
}
});
Added: trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/JournalConstants.java
===================================================================
--- trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/JournalConstants.java (rev 0)
+++ trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/JournalConstants.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -0,0 +1,11 @@
+package org.hornetq.core.journal.impl;
+
+public final class JournalConstants
+{
+
+ public static final int DEFAULT_JOURNAL_BUFFER_SIZE_AIO = 490 * 1024;
+ public static final int DEFAULT_JOURNAL_BUFFER_TIMEOUT_AIO = (int)(1000000000d / 2000);
+ public static final int DEFAULT_JOURNAL_BUFFER_TIMEOUT_NIO = (int)(1000000000d / 300);
+ public static final int DEFAULT_JOURNAL_BUFFER_SIZE_NIO = 490 * 1024;
+
+}
Modified: trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/NIOSequentialFileFactory.java
===================================================================
--- trunk/hornetq-core/src/main/java/org/hornetq/core/journal/impl/NIOSequentialFileFactory.java 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/hornetq-journal/src/main/java/org/hornetq/core/journal/impl/NIOSequentialFileFactory.java 2011-05-26 15:06:40 UTC (rev 10740)
@@ -15,15 +15,14 @@
import java.nio.ByteBuffer;
-import org.hornetq.core.config.impl.ConfigurationImpl;
import org.hornetq.core.journal.SequentialFile;
import org.hornetq.core.journal.SequentialFileFactory;
import org.hornetq.core.logging.Logger;
/**
- *
+ *
* A NIOSequentialFileFactory
- *
+ *
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
* @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
*
@@ -36,8 +35,8 @@
{
this(journalDir,
false,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_SIZE_NIO,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_TIMEOUT_NIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_SIZE_NIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_TIMEOUT_NIO,
false);
}
@@ -45,8 +44,8 @@
{
this(journalDir,
buffered,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_SIZE_NIO,
- ConfigurationImpl.DEFAULT_JOURNAL_BUFFER_TIMEOUT_NIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_SIZE_NIO,
+ JournalConstants.DEFAULT_JOURNAL_BUFFER_TIMEOUT_NIO,
false);
}
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2011-05-26 12:50:50 UTC (rev 10739)
+++ trunk/pom.xml 2011-05-26 15:06:40 UTC (rev 10740)
@@ -120,18 +120,19 @@
</contributors>
<modules>
+ <module>hornetq-bootstrap</module>
+ <module>hornetq-commons</module>
+ <module>hornetq-core-client</module>
<module>hornetq-core</module>
- <module>hornetq-core-client</module>
+ <module>hornetq-jboss-as-integration</module>
+ <module>hornetq-jms-client</module>
<module>hornetq-jms</module>
- <module>hornetq-jms-client</module>
+ <module>hornetq-journal</module>
<module>hornetq-ra</module>
- <module>hornetq-commons</module>
- <module>hornetq-bootstrap</module>
- <module>hornetq-jboss-as-integration</module>
+ <module>hornetq-rest</module>
+ <module>hornetq-service-sar</module>
+ <module>hornetq-spring-integration</module>
<module>hornetq-twitter-integration</module>
- <module>hornetq-spring-integration</module>
- <module>hornetq-service-sar</module>
- <module>hornetq-rest</module>
</modules>
<dependencyManagement>
More information about the hornetq-commits
mailing list