You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/09 19:53:56 UTC
[23/51] [partial] incubator-juneau git commit: Rename project
directories.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackInputStream.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackInputStream.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackInputStream.java
new file mode 100644
index 0000000..918af13
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackInputStream.java
@@ -0,0 +1,482 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import static org.apache.juneau.msgpack.DataType.*;
+
+import java.io.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Specialized input stream for parsing MessagePack streams.
+ * <p>
+ * <b>Note: This class is not intended for external use.</b>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackInputStream extends InputStream {
+
+ private final InputStream is;
+ private DataType currentDataType;
+ private long length;
+ private int lastByte;
+ private int extType;
+ int pos = 0;
+
+ // Data type quick-lookup table.
+ private static final DataType[] TYPES = new DataType[] {
+ /*0x0?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x1?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x2?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x3?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x4?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x5?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x6?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x7?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0x8?*/ MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,
+ /*0x9?*/ ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,
+ /*0xA?*/ STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,
+ /*0xB?*/ STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,
+ /*0xC?*/ NULL, INVALID, BOOLEAN, BOOLEAN, BIN, BIN, BIN, EXT, EXT, EXT, FLOAT, DOUBLE, INT, INT, LONG, LONG,
+ /*0xD?*/ INT, INT, INT, LONG, EXT, EXT, EXT, EXT, EXT, STRING, STRING, STRING, ARRAY, ARRAY, MAP, MAP,
+ /*0xE?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ /*0xF?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT
+ };
+
+ /**
+ * Constructor.
+ * @param is The input stream being wrapped.
+ */
+ protected MsgPackInputStream(InputStream is) {
+ this.is = is;
+ }
+
+ @Override /* InputStream */
+ public int read() throws IOException {
+ int i = is.read();
+ if (i > 0)
+ pos++;
+ return i;
+ }
+
+ /**
+ * Reads the data type flag from the stream.
+ * This is the byte that indicates what kind of data follows.
+ */
+ DataType readDataType() throws IOException {
+ int i = read();
+ if (i == -1)
+ throw new IOException("Unexpected end of file found at position " + pos);
+ currentDataType = TYPES[i];
+ switch (currentDataType) {
+ case NULL:
+ case FLOAT: {
+ length = 4;
+ break;
+ }
+ case DOUBLE: {
+ length = 8;
+ break;
+ }
+ case BOOLEAN: {
+ lastByte = i;
+ break;
+ }
+ case INT: {
+ // positive fixnum stores 7-bit positive integer
+ // +--------+
+ // |0XXXXXXX|
+ // +--------+
+ //
+ // negative fixnum stores 5-bit negative integer
+ // +--------+
+ // |111YYYYY|
+ // +--------+
+ //
+ // * 0XXXXXXX is 8-bit unsigned integer
+ // * 111YYYYY is 8-bit signed integer
+ //
+ // uint 8 stores a 8-bit unsigned integer
+ // +--------+--------+
+ // | 0xcc |ZZZZZZZZ|
+ // +--------+--------+
+ //
+ // uint 16 stores a 16-bit big-endian unsigned integer
+ // +--------+--------+--------+
+ // | 0xcd |ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+
+ //
+ // uint 32 stores a 32-bit big-endian unsigned integer
+ // +--------+--------+--------+--------+--------+
+ // | 0xce |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+--------+--------+
+ //
+ // uint 64 stores a 64-bit big-endian unsigned integer
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ // | 0xcf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ //
+ // int 8 stores a 8-bit signed integer
+ // +--------+--------+
+ // | 0xd0 |ZZZZZZZZ|
+ // +--------+--------+
+ //
+ // int 16 stores a 16-bit big-endian signed integer
+ // +--------+--------+--------+
+ // | 0xd1 |ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+
+ //
+ // int 32 stores a 32-bit big-endian signed integer
+ // +--------+--------+--------+--------+--------+
+ // | 0xd2 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+--------+--------+
+ //
+ // int 64 stores a 64-bit big-endian signed integer
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ // | 0xd3 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ lastByte = i;
+ if (i <= POSFIXINT_U)
+ length = 0;
+ else if (i >= NEGFIXINT_L)
+ length = -1;
+ else if (i == INT8 || i == UINT8)
+ length = 1;
+ else if (i == INT16 || i == UINT16)
+ length = 2;
+ else if (i == INT32)
+ length = 4;
+ else
+ length = 0;
+ break;
+ }
+ case LONG: {
+ if (i == UINT32)
+ length = 4;
+ else if (i == INT64 || i == UINT64)
+ length = 8;
+ else
+ length = 0;
+ break;
+ }
+ case STRING:{
+ // fixstr stores a byte array whose length is upto 31 bytes:
+ // +--------+========+
+ // |101XXXXX| data |
+ // +--------+========+
+ //
+ // str 8 stores a byte array whose length is upto (2^8)-1 bytes:
+ // +--------+--------+========+
+ // | 0xd9 |YYYYYYYY| data |
+ // +--------+--------+========+
+ //
+ // str 16 stores a byte array whose length is upto (2^16)-1 bytes:
+ // +--------+--------+--------+========+
+ // | 0xda |ZZZZZZZZ|ZZZZZZZZ| data |
+ // +--------+--------+--------+========+
+ //
+ // str 32 stores a byte array whose length is upto (2^32)-1 bytes:
+ // +--------+--------+--------+--------+--------+========+
+ // | 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data |
+ // +--------+--------+--------+--------+--------+========+
+ //
+ // where
+ // * XXXXX is a 5-bit unsigned integer which represents N
+ // * YYYYYYYY is a 8-bit unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ is a 16-bit big-endian unsigned integer which represents N
+ // * AAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA is a 32-bit big-endian unsigned integer which represents N
+ // * N is the length of data
+ if (i <= FIXSTR_U)
+ length = i & 0x1F;
+ else if (i == STR8)
+ length = readUInt1();
+ else if (i == STR16)
+ length = readUInt2();
+ else
+ length = readUInt4();
+ break;
+ }
+ case ARRAY: {
+ // fixarray stores an array whose length is upto 15 elements:
+ // +--------+~~~~~~~~~~~~~~~~~+
+ // |1001XXXX| N objects |
+ // +--------+~~~~~~~~~~~~~~~~~+
+ //
+ // array 16 stores an array whose length is upto (2^16)-1 elements:
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdc |YYYYYYYY|YYYYYYYY| N objects |
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // array 32 stores an array whose length is upto (2^32)-1 elements:
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdd |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N objects |
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // where
+ // * XXXX is a 4-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // N is the size of a array
+ if (i <= FIXARRAY_U)
+ length = i & 0x0F;
+ else if (i == ARRAY16)
+ length = readUInt2();
+ else
+ length = readUInt4();
+ break;
+ }
+ case BIN:{
+ // bin 8 stores a byte array whose length is upto (2^8)-1 bytes:
+ // +--------+--------+========+
+ // | 0xc4 |XXXXXXXX| data |
+ // +--------+--------+========+
+ //
+ // bin 16 stores a byte array whose length is upto (2^16)-1 bytes:
+ // +--------+--------+--------+========+
+ // | 0xc5 |YYYYYYYY|YYYYYYYY| data |
+ // +--------+--------+--------+========+
+ //
+ // bin 32 stores a byte array whose length is upto (2^32)-1 bytes:
+ // +--------+--------+--------+--------+--------+========+
+ // | 0xc6 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| data |
+ // +--------+--------+--------+--------+--------+========+
+ //
+ // where
+ // * XXXXXXXX is a 8-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // * N is the length of data
+ if (i == BIN8)
+ length = readUInt1();
+ else if (i == BIN16)
+ length = readUInt2();
+ else
+ length = readUInt4();
+ break;
+ }
+ case EXT:{
+ // fixext 1 stores an integer and a byte array whose length is 1 byte
+ // +--------+--------+--------+
+ // | 0xd4 | type | data |
+ // +--------+--------+--------+
+ //
+ // fixext 2 stores an integer and a byte array whose length is 2 bytes
+ // +--------+--------+--------+--------+
+ // | 0xd5 | type | data |
+ // +--------+--------+--------+--------+
+ //
+ // fixext 4 stores an integer and a byte array whose length is 4 bytes
+ // +--------+--------+--------+--------+--------+--------+
+ // | 0xd6 | type | data |
+ // +--------+--------+--------+--------+--------+--------+
+ //
+ // fixext 8 stores an integer and a byte array whose length is 8 bytes
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ // | 0xd7 | type | data |
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ //
+ // fixext 16 stores an integer and a byte array whose length is 16 bytes
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ // | 0xd8 | type | data
+ // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+ // +--------+--------+--------+--------+--------+--------+--------+--------+
+ // data (cont.) |
+ // +--------+--------+--------+--------+--------+--------+--------+--------+
+ //
+ // ext 8 stores an integer and a byte array whose length is upto (2^8)-1 bytes:
+ // +--------+--------+--------+========+
+ // | 0xc7 |XXXXXXXX| type | data |
+ // +--------+--------+--------+========+
+ //
+ // ext 16 stores an integer and a byte array whose length is upto (2^16)-1 bytes:
+ // +--------+--------+--------+--------+========+
+ // | 0xc8 |YYYYYYYY|YYYYYYYY| type | data |
+ // +--------+--------+--------+--------+========+
+ //
+ // ext 32 stores an integer and a byte array whose length is upto (2^32)-1 bytes:
+ // +--------+--------+--------+--------+--------+--------+========+
+ // | 0xc9 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| type | data |
+ // +--------+--------+--------+--------+--------+--------+========+
+ //
+ // where
+ // * XXXXXXXX is a 8-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a big-endian 32-bit unsigned integer which represents N
+ // * N is a length of data
+ // * type is a signed 8-bit signed integer
+ // * type < 0 is reserved for future extension including 2-byte type information
+ if (i == FIXEXT1)
+ length = 1;
+ else if (i == FIXEXT2)
+ length = 2;
+ else if (i == FIXEXT4)
+ length = 4;
+ else if (i == FIXEXT8)
+ length = 8;
+ else if (i == FIXEXT16)
+ length = 16;
+ else if (i == EXT8)
+ length = readUInt1();
+ else if (i == EXT16)
+ length = readUInt2();
+ else if (i == EXT32)
+ length = readUInt4();
+ extType = is.read();
+
+ break;
+ }
+ case MAP:{
+ // fixmap stores a map whose length is upto 15 elements
+ // +--------+~~~~~~~~~~~~~~~~~+
+ // |1000XXXX| N*2 objects |
+ // +--------+~~~~~~~~~~~~~~~~~+
+ //
+ // map 16 stores a map whose length is upto (2^16)-1 elements
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xde |YYYYYYYY|YYYYYYYY| N*2 objects |
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // map 32 stores a map whose length is upto (2^32)-1 elements
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N*2 objects |
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // where
+ // * XXXX is a 4-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // * N is the size of a map
+ // * odd elements in objects are keys of a map
+ // * the next element of a key is its associated value
+ if (i <= FIXMAP_U)
+ length = i & 0x0F;
+ else if (i == MAP16)
+ length = readUInt2();
+ else
+ length = readUInt4();
+ break;
+ }
+ default:
+ throw new IOException("Invalid flag 0xC1 detected in stream.");
+ }
+ return currentDataType;
+ }
+
+ /**
+ * Returns the length value for the field.
+ * For ints/floats/bins/strings, this is the number of bytes that the field takes up (minus the data-type flag).
+ * For arrays, it's the number of array entries.
+ * For maps, it's the number of map entries.
+ */
+ long readLength() {
+ return length;
+ }
+
+ /**
+ * Read a boolean from the stream.
+ */
+ boolean readBoolean() {
+ return lastByte == TRUE;
+ }
+
+ /**
+ * Read a string from the stream.
+ */
+ String readString() throws IOException {
+ return new String(readBinary(), IOUtils.UTF8);
+ }
+
+ /**
+ * Read a binary field from the stream.
+ */
+ byte[] readBinary() throws IOException {
+ byte[] b = new byte[(int)length];
+ is.read(b);
+ return b;
+ }
+
+ /**
+ * Read an integer from the stream.
+ */
+ int readInt() throws IOException {
+ if (length == 0)
+ return lastByte;
+ if (length == 1)
+ return is.read();
+ if (length == 2)
+ return (is.read() << 8) | is.read();
+ int i = is.read(); i <<= 8; i |= is.read(); i <<= 8; i |= is.read(); i <<= 8; i |= is.read();
+ return i;
+ }
+
+ /**
+ * Read a float from the stream.
+ */
+ float readFloat() throws IOException {
+ return Float.intBitsToFloat(readInt());
+ }
+
+ /**
+ * Read a double from the stream.
+ */
+ double readDouble() throws IOException {
+ return Double.longBitsToDouble(readLong());
+ }
+
+ /**
+ * Read 64-bit long from the stream.
+ */
+ long readLong() throws IOException {
+ if (length == 4)
+ return readUInt4();
+ long l = is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read();
+ return l;
+ }
+
+ /**
+ * Return the extended-format type.
+ * Currently not used.
+ */
+ int getExtType() {
+ return extType;
+ }
+
+ /**
+ * Read one byte from the stream.
+ */
+ private int readUInt1() throws IOException {
+ return is.read();
+ }
+
+ /**
+ * Read two bytes from the stream.
+ */
+ private int readUInt2() throws IOException {
+ return (is.read() << 8) | is.read();
+ }
+
+ /**
+ * Read four bytes from the stream.
+ */
+ private long readUInt4() throws IOException {
+ long l = is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read();
+ return l;
+ }
+
+ /**
+ * Return the current read position in the stream (i.e. number of bytes we've read so far).
+ */
+ int getPosition() {
+ return pos;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
new file mode 100644
index 0000000..3ffed66
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
@@ -0,0 +1,322 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import static org.apache.juneau.msgpack.DataType.*;
+
+import java.io.*;
+import java.math.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * Specialized output stream for serializing MessagePack streams.
+ * <p>
+ * <b>Note: This class is not intended for external use.</b>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackOutputStream extends OutputStream {
+
+ private final OutputStream os;
+
+ /**
+ * Constructor.
+ * @param os The output stream being wrapped.
+ */
+ protected MsgPackOutputStream(OutputStream os) {
+ this.os = os;
+ }
+
+ @Override /* OutputStream */
+ public void write(int b) throws IOException {
+ os.write(b);
+ }
+
+ /**
+ * Same as {@link #write(int)}.
+ */
+ final MsgPackOutputStream append(byte b) throws IOException {
+ os.write(b);
+ return this;
+ }
+
+ /**
+ * Same as {@link #write(byte[])}.
+ */
+ final MsgPackOutputStream append(byte[] b) throws IOException {
+ os.write(b);
+ return this;
+ }
+
+ /**
+ * Appends one byte to the stream.
+ */
+ final MsgPackOutputStream append1(int i) throws IOException {
+ os.write(i);
+ return this;
+ }
+
+ /**
+ * Appends two bytes to the stream.
+ */
+ final MsgPackOutputStream append2(int i) throws IOException {
+ return append1(i>>8).append1(i);
+ }
+
+ /**
+ * Appends four bytes to the stream.
+ */
+ final MsgPackOutputStream append4(int i) throws IOException {
+ return append1(i>>24).append1(i>>16).append1(i>>8).append1(i);
+ }
+
+ /**
+ * Appends eight bytes to the stream.
+ */
+ final MsgPackOutputStream append8(long l) throws IOException {
+ return append1((int)(l>>56)).append1((int)(l>>48)).append1((int)(l>>40)).append1((int)(l>>32)).append1((int)(l>>24)).append1((int)(l>>16)).append1((int)(l>>8)).append1((int)(l));
+ }
+
+ /**
+ * Appends a NULL flag to the stream.
+ */
+ final MsgPackOutputStream appendNull() throws IOException {
+ return append1(NIL);
+ }
+
+ /**
+ * Appends a boolean to the stream.
+ */
+ final MsgPackOutputStream appendBoolean(boolean b) throws IOException {
+ return append1(b ? TRUE : FALSE);
+ }
+
+ /**
+ * Appends an integer to the stream.
+ */
+ final MsgPackOutputStream appendInt(int i) throws IOException {
+ // POSFIXINT_L = 0x00, // pos fixint 0xxxxxxx 0x00 - 0x7f
+ // POSFIXINT_U = 0x7F,
+ // UINT8 = 0xCC, // uint 8 11001100 0xcc
+ // UINT16 = 0xCD, // uint 16 11001101 0xcd
+ // UINT32 = 0xCE, // uint 32 11001110 0xce
+ // UINT64 = 0xCF, // uint 64 11001111 0xcf
+ // INT8 = 0xD0, // int 8 11010000 0xd0
+ // INT16 = 0xD1, // int 16 11010001 0xd1
+ // INT32 = 0xD2, // int 32 11010010 0xd2
+ // INT64 = 0xD3, // int 64 11010011 0xd3
+ // NEGFIXINT_L = 0xE0, // neg fixint 111xxxxx 0xe0 - 0xff
+ // NEGFIXINT_U = 0xFF;
+ if (i >= 0) {
+ if (i < (1<<7))
+ return append1(i);
+ if (i < (1<<15))
+ return append1(INT16).append2(i);
+ return append1(INT32).append4(i);
+ }
+ if (i > -(1<<6))
+ return append((byte)(0xE0 | -i));
+ if (i > -(1<<7))
+ return append1(INT8).append1(i);
+ if (i > -(1<<15))
+ return append1(INT16).append2(i);
+ return append1(INT32).append4(i);
+ }
+
+ final long L2X31 = ((long)(1<<30))*2;
+
+ /**
+ * Appends a long to the stream.
+ */
+ final MsgPackOutputStream appendLong(long l) throws IOException {
+ if (l < L2X31 && l > -(L2X31))
+ return appendInt((int)l);
+ return append1(INT64).append8(l);
+ }
+
+ /**
+ * Appends a generic Number to the stream.
+ */
+ final MsgPackOutputStream appendNumber(Number n) throws IOException {
+ Class<?> c = n.getClass();
+ if (c == Integer.class || c == Short.class || c == Byte.class || c == AtomicInteger.class)
+ return appendInt(n.intValue());
+ if (c == Long.class || c == AtomicLong.class)
+ return appendLong(n.longValue());
+ if (c == Float.class)
+ return appendFloat(n.floatValue());
+ if (c == Double.class)
+ return appendDouble(n.doubleValue());
+ if (c == BigInteger.class)
+ return appendLong(n.longValue());
+ if (c == BigDecimal.class)
+ return appendDouble(n.doubleValue());
+ return appendInt(0);
+ }
+
+ /**
+ * Appends a float to the stream.
+ */
+ final MsgPackOutputStream appendFloat(float f) throws IOException {
+ // FLOAT32 = 0xCA, // float 32 11001010 0xca
+ return append1(FLOAT32).append4(Float.floatToIntBits(f));
+
+ }
+
+ /**
+ * Appends a double to the stream.
+ */
+ final MsgPackOutputStream appendDouble(double d) throws IOException {
+ // FLOAT64 = 0xCB, // float 64 11001011 0xcb
+ return append1(FLOAT64).append8(Double.doubleToLongBits(d));
+ }
+
+ /**
+ * Appends a string to the stream.
+ */
+ final MsgPackOutputStream appendString(CharSequence cs) throws IOException {
+
+ // fixstr stores a byte array whose length is upto 31 bytes:
+ // +--------+========+
+ // |101XXXXX| data |
+ // +--------+========+
+ //
+ // str 8 stores a byte array whose length is upto (2^8)-1 bytes:
+ // +--------+--------+========+
+ // | 0xd9 |YYYYYYYY| data |
+ // +--------+--------+========+
+ //
+ // str 16 stores a byte array whose length is upto (2^16)-1 bytes:
+ // +--------+--------+--------+========+
+ // | 0xda |ZZZZZZZZ|ZZZZZZZZ| data |
+ // +--------+--------+--------+========+
+ //
+ // str 32 stores a byte array whose length is upto (2^32)-1 bytes:
+ // +--------+--------+--------+--------+--------+========+
+ // | 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data |
+ // +--------+--------+--------+--------+--------+========+
+ // where
+ // * XXXXX is a 5-bit unsigned integer which represents N
+ // * YYYYYYYY is a 8-bit unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ is a 16-bit big-endian unsigned integer which represents N
+ // * AAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA is a 32-bit big-endian unsigned integer which represents N
+ // * N is the length of data
+
+ byte[] b = cs.toString().getBytes("UTF-8");
+ if (b.length < 32)
+ return append1(0xA0 + b.length).append(b);
+ if (b.length < (1<<8))
+ return append1(STR8).append1(b.length).append(b);
+ if (b.length < (1<<16))
+ return append1(STR16).append2(b.length).append(b);
+ return append1(STR32).append4(b.length).append(b);
+ }
+
+ /**
+ * Appends a binary field to the stream.
+ */
+ final MsgPackOutputStream appendBinary(byte[] b) throws IOException {
+ // bin 8 stores a byte array whose length is upto (2^8)-1 bytes:
+ // +--------+--------+========+
+ // | 0xc4 |XXXXXXXX| data |
+ // +--------+--------+========+
+ //
+ // bin 16 stores a byte array whose length is upto (2^16)-1 bytes:
+ // +--------+--------+--------+========+
+ // | 0xc5 |YYYYYYYY|YYYYYYYY| data |
+ // +--------+--------+--------+========+
+ //
+ // bin 32 stores a byte array whose length is upto (2^32)-1 bytes:
+ // +--------+--------+--------+--------+--------+========+
+ // | 0xc6 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| data |
+ // +--------+--------+--------+--------+--------+========+
+ //
+ // where
+ // * XXXXXXXX is a 8-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // * N is the length of data
+
+ if (b.length < (1<<8))
+ return append1(BIN8).append1(b.length).append(b);
+ if (b.length < (1<<16))
+ return append1(BIN16).append2(b.length).append(b);
+ return append1(BIN32).append4(b.length).append(b);
+ }
+
+ /**
+ * Appends an array data type flag to the stream.
+ */
+ final MsgPackOutputStream startArray(int size) throws IOException {
+ // fixarray stores an array whose length is upto 15 elements:
+ // +--------+~~~~~~~~~~~~~~~~~+
+ // |1001XXXX| N objects |
+ // +--------+~~~~~~~~~~~~~~~~~+
+ //
+ // array 16 stores an array whose length is upto (2^16)-1 elements:
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdc |YYYYYYYY|YYYYYYYY| N objects |
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // array 32 stores an array whose length is upto (2^32)-1 elements:
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdd |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N objects |
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // where
+ // * XXXX is a 4-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // N is the size of a array
+
+ if (size < 16)
+ return append1(0x90 + size);
+ if (size < (1<<16))
+ return append1(ARRAY16).append2(size);
+ return append1(ARRAY32).append4(size);
+ }
+
+ /**
+ * Appends a map data type flag to the stream.
+ */
+ final MsgPackOutputStream startMap(int size) throws IOException {
+ // fixmap stores a map whose length is upto 15 elements
+ // +--------+~~~~~~~~~~~~~~~~~+
+ // |1000XXXX| N*2 objects |
+ // +--------+~~~~~~~~~~~~~~~~~+
+ //
+ // map 16 stores a map whose length is upto (2^16)-1 elements
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xde |YYYYYYYY|YYYYYYYY| N*2 objects |
+ // +--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // map 32 stores a map whose length is upto (2^32)-1 elements
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ // | 0xdf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N*2 objects |
+ // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
+ //
+ // where
+ // * XXXX is a 4-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
+ // * N is the size of a map
+ // * odd elements in objects are keys of a map
+ // * the next element of a key is its associated value
+
+ if (size < 16)
+ return append1(0x80 + size);
+ if (size < (1<<16))
+ return append1(MAP16).append2(size);
+ return append1(MAP32).append4(size);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
new file mode 100644
index 0000000..ec62363
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -0,0 +1,261 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import static org.apache.juneau.msgpack.DataType.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Parses a MessagePack stream into a POJO model.
+ *
+ *
+ * <h6 class='topic'>Media types</h6>
+ * <p>
+ * Handles <code>Content-Type</code> types: <code>octal/msgpack</code>
+ *
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * This class has the following properties associated with it:
+ * <ul>
+ * <li>{@link MsgPackParserContext}
+ * </ul>
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+@Consumes({"octal/msgpack"})
+public final class MsgPackParser extends InputStreamParser {
+
+ /** Default parser, all default settings.*/
+ public static final MsgPackParser DEFAULT = new MsgPackParser().lock();
+
+ /**
+ * Workhorse method.
+ */
+ private <T> T parseAnything(MsgPackParserSession session, ClassMeta<T> nt, MsgPackInputStream is, Object outer) throws Exception {
+
+ BeanContext bc = session.getBeanContext();
+ if (nt == null)
+ nt = (ClassMeta<T>)object();
+ PojoTransform<T,Object> transform = (PojoTransform<T,Object>)nt.getPojoTransform();
+ ClassMeta<?> ft = nt.getTransformedClassMeta();
+ session.setCurrentClass(ft);
+
+ Object o = null;
+ DataType dt = is.readDataType();
+ int length = (int)is.readLength();
+
+ if (dt != DataType.NULL) {
+ if (dt == BOOLEAN)
+ o = is.readBoolean();
+ else if (dt == INT)
+ o = is.readInt();
+ else if (dt == LONG)
+ o = is.readLong();
+ else if (dt == FLOAT)
+ o = is.readFloat();
+ else if (dt == DOUBLE)
+ o = is.readDouble();
+ else if (dt == STRING)
+ o = session.trim(is.readString());
+ else if (dt == BIN)
+ o = is.readBinary();
+ else if (dt == ARRAY && ft.isObject()) {
+ ObjectList ol = new ObjectList(bc);
+ for (int i = 0; i < length; i++)
+ ol.add(parseAnything(session, object(), is, outer));
+ o = ol;
+ } else if (dt == MAP && ft.isObject()) {
+ ObjectMap om = new ObjectMap(bc);
+ for (int i = 0; i < length; i++)
+ om.put(parseAnything(session, string(), is, outer), parseAnything(session, object(), is, om));
+ o = om.cast();
+ }
+
+ if (ft.isObject()) {
+ // Do nothing.
+ } else if (ft.isBoolean() || ft.isCharSequence() || ft.isChar() || ft.isNumber()) {
+ o = bc.convertToType(o, ft);
+ } else if (ft.isMap()) {
+ if (dt == MAP) {
+ Map m = (ft.canCreateNewInstance(outer) ? (Map)ft.newInstance(outer) : new ObjectMap(bc));
+ for (int i = 0; i < length; i++) {
+ Object key = parseAnything(session, ft.getKeyType(), is, outer);
+ ClassMeta<?> vt = ft.getValueType();
+ Object value = parseAnything(session, vt, is, m);
+ setName(vt, value, key);
+ m.put(key, value);
+ }
+ o = m;
+ } else {
+ throw new ParseException(session, "Invalid data type {0} encountered for parse type {1}", dt, ft);
+ }
+ } else if (ft.canCreateNewInstanceFromObjectMap(outer)) {
+ ObjectMap m = new ObjectMap(bc);
+ for (int i = 0; i < length; i++)
+ m.put(parseAnything(session, string(), is, outer), parseAnything(session, object(), is, m));
+ o = ft.newInstanceFromObjectMap(outer, m);
+ } else if (ft.canCreateNewBean(outer)) {
+ if (dt == MAP) {
+ BeanMap m = bc.newBeanMap(outer, ft.getInnerClass());
+ for (int i = 0; i < length; i++) {
+ String pName = parseAnything(session, string(), is, m.getBean(false));
+ BeanPropertyMeta<?> bpm = m.getPropertyMeta(pName);
+ if (bpm == null) {
+ if (pName.equals("_class"))
+ parseAnything(session, bc.string(), is, null);
+ else
+ onUnknownProperty(session, pName, m, 0, is.getPosition());
+ } else {
+ ClassMeta<?> cm = bpm.getClassMeta();
+ Object value = parseAnything(session, cm, is, m.getBean(false));
+ setName(cm, value, pName);
+ bpm.set(m, value);
+ }
+ }
+ o = m.getBean();
+ } else {
+ throw new ParseException(session, "Invalid data type {0} encountered for parse type {1}", dt, ft);
+ }
+ } else if (ft.canCreateNewInstanceFromString(outer) && dt == STRING) {
+ o = ft.newInstanceFromString(outer, o == null ? "" : o.toString());
+ } else if (ft.canCreateNewInstanceFromNumber(outer) && dt.isOneOf(INT, LONG, FLOAT, DOUBLE)) {
+ o = ft.newInstanceFromNumber(outer, (Number)o);
+ } else if (ft.isCollection()) {
+ if (dt == MAP) {
+ ObjectMap m = new ObjectMap(bc);
+ for (int i = 0; i < length; i++)
+ m.put(parseAnything(session, string(), is, outer), parseAnything(session, object(), is, m));
+ o = m.cast();
+ } else if (dt == ARRAY) {
+ Collection l = (ft.canCreateNewInstance(outer) ? (Collection)ft.newInstance() : new ObjectList(bc));
+ for (int i = 0; i < length; i++)
+ l.add(parseAnything(session, ft.getElementType(), is, l));
+ o = l;
+ } else {
+ throw new ParseException(session, "Invalid data type {0} encountered for parse type {1}", dt, ft);
+ }
+ } else if (ft.isArray()) {
+ if (dt == MAP) {
+ ObjectMap m = new ObjectMap(bc);
+ for (int i = 0; i < length; i++)
+ m.put(parseAnything(session, string(), is, outer), parseAnything(session, object(), is, m));
+ o = m.cast();
+ } else if (dt == ARRAY) {
+ Collection l = (ft.isCollection() && ft.canCreateNewInstance(outer) ? (Collection)ft.newInstance() : new ObjectList(bc));
+ for (int i = 0; i < length; i++)
+ l.add(parseAnything(session, ft.getElementType(), is, l));
+ o = bc.toArray(ft, l);
+ } else {
+ throw new ParseException(session, "Invalid data type {0} encountered for parse type {1}", dt, ft);
+ }
+ } else if (dt == MAP) {
+ ObjectMap m = new ObjectMap(bc);
+ for (int i = 0; i < length; i++)
+ m.put(parseAnything(session, string(), is, outer), parseAnything(session, object(), is, m));
+ if (m.containsKey("_class"))
+ o = m.cast();
+ else
+ throw new ParseException(session, "Class ''{0}'' could not be instantiated. Reason: ''{1}''", ft.getInnerClass().getName(), ft.getNotABeanReason());
+ } else {
+ throw new ParseException(session, "Invalid data type {0} encountered for parse type {1}", dt, ft);
+ }
+ }
+
+ if (transform != null && o != null)
+ o = transform.normalize(o, nt);
+
+ if (outer != null)
+ setParent(nt, o, outer);
+
+ return (T)o;
+ }
+
+ //--------------------------------------------------------------------------------
+ // Overridden methods
+ //--------------------------------------------------------------------------------
+
+ @Override /* Parser */
+ public MsgPackParserSession createSession(Object input, ObjectMap op, Method javaMethod, Object outer) {
+ return new MsgPackParserSession(getContext(MsgPackParserContext.class), getBeanContext(), input, op, javaMethod, outer);
+ }
+
+ @Override /* Parser */
+ protected <T> T doParse(ParserSession session, ClassMeta<T> type) throws Exception {
+ MsgPackParserSession s = (MsgPackParserSession)session;
+ type = s.getBeanContext().normalizeClassMeta(type);
+ MsgPackInputStream is = s.getInputStream();
+ T o = parseAnything(s, type, is, s.getOuter());
+ return o;
+ }
+
+ @Override /* Parser */
+ public MsgPackParser setProperty(String property, Object value) throws LockedException {
+ super.setProperty(property, value);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackParser setProperties(ObjectMap properties) throws LockedException {
+ super.setProperties(properties);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackParser addNotBeanClasses(Class<?>...classes) throws LockedException {
+ super.addNotBeanClasses(classes);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackParser addTransforms(Class<?>...classes) throws LockedException {
+ super.addTransforms(classes);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public <T> MsgPackParser addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+ super.addImplClass(interfaceClass, implClass);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackParser setClassLoader(ClassLoader classLoader) throws LockedException {
+ super.setClassLoader(classLoader);
+ return this;
+ }
+
+ @Override /* Lockable */
+ public MsgPackParser lock() {
+ super.lock();
+ return this;
+ }
+
+ @Override /* Lockable */
+ public MsgPackParser clone() {
+ try {
+ return (MsgPackParser)super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e); // Shouldn't happen
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserContext.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserContext.java
new file mode 100644
index 0000000..2ed5522
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserContext.java
@@ -0,0 +1,49 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * Configurable properties on the {@link MsgPackParser} class.
+ * <p>
+ * Context properties are set by calling {@link ContextFactory#setProperty(String, Object)} on the context factory
+ * returned {@link CoreApi#getContextFactory()}.
+ * <p>
+ * The following convenience methods are also provided for setting context properties:
+ * <ul>
+ * <li>{@link MsgPackParser#setProperty(String,Object)}
+ * <li>{@link MsgPackParser#setProperties(ObjectMap)}
+ * <li>{@link MsgPackParser#addNotBeanClasses(Class[])}
+ * <li>{@link MsgPackParser#addTransforms(Class[])}
+ * <li>{@link MsgPackParser#addImplClass(Class,Class)}
+ * </ul>
+ * <p>
+ * See {@link ContextFactory} for more information about context properties.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackParserContext extends ParserContext {
+
+ /**
+ * Constructor.
+ * <p>
+ * Typically only called from {@link ContextFactory#getContext(Class)}.
+ *
+ * @param cf The factory that created this context.
+ */
+ public MsgPackParserContext(ContextFactory cf) {
+ super(cf);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
new file mode 100644
index 0000000..4f5057c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
@@ -0,0 +1,70 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link MsgPackParser}.
+ * <p>
+ * This class is NOT thread safe. It is meant to be discarded after one-time use.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackParserSession extends ParserSession {
+
+ private MsgPackInputStream inputStream;
+
+ /**
+ * Create a new session using properties specified in the context.
+ *
+ * @param ctx The context creating this session object.
+ * The context contains all the configuration settings for this object.
+ * @param beanContext The bean context being used.
+ * @param input The input. Can be any of the following types:
+ * <ul>
+ * <li><jk>null</jk>
+ * <li>{@link Reader}
+ * <li>{@link CharSequence}
+ * <li>{@link InputStream} containing UTF-8 encoded text.
+ * <li>{@link File} containing system encoded text.
+ * </ul>
+ * @param op The override properties.
+ * These override any context properties defined in the context.
+ * @param javaMethod The java method that called this parser, usually the method in a REST servlet.
+ * @param outer The outer object for instantiating top-level non-static inner classes.
+ */
+ public MsgPackParserSession(MsgPackParserContext ctx, BeanContext beanContext, Object input, ObjectMap op, Method javaMethod, Object outer) {
+ super(ctx, beanContext, input, op, javaMethod, outer);
+ }
+
+ @Override /* ParserSession */
+ public MsgPackInputStream getInputStream() throws ParseException {
+ if (inputStream == null)
+ inputStream = new MsgPackInputStream(super.getInputStream());
+ return inputStream;
+ }
+
+ @Override /* ParserSession */
+ public Map<String,Object> getLastLocation() {
+ Map<String,Object> m = super.getLastLocation();
+ if (inputStream != null)
+ m.put("position", inputStream.getPosition());
+ return m;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
new file mode 100644
index 0000000..76aa138
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -0,0 +1,280 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Serializes POJO models to MessagePack.
+ *
+ *
+ * <h6 class='topic'>Media types</h6>
+ * <p>
+ * Handles <code>Accept</code> types: <code>octal/msgpack</code>
+ * <p>
+ * Produces <code>Content-Type</code> types: <code>octal/msgpack</code>
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * This class has the following properties associated with it:
+ * <ul>
+ * <li>{@link MsgPackSerializerContext}
+ * <li>{@link SerializerContext}
+ * <li>{@link BeanContext}
+ * </ul>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@Produces({"octal/msgpack"})
+public class MsgPackSerializer extends OutputStreamSerializer {
+
+ /** Default serializer, all default settings.*/
+ public static final MsgPackSerializer DEFAULT = new MsgPackSerializer().lock();
+
+ /**
+ * Workhorse method. Determines the type of object, and then calls the
+ * appropriate type-specific serialization method.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ MsgPackOutputStream serializeAnything(MsgPackSerializerSession session, MsgPackOutputStream out, Object o, ClassMeta<?> eType, String attrName, BeanPropertyMeta pMeta) throws Exception {
+ BeanContext bc = session.getBeanContext();
+
+ if (o == null)
+ return out.appendNull();
+
+ if (eType == null)
+ eType = object();
+
+ boolean addClassAttr; // Add "_class" attribute to element?
+ ClassMeta<?> aType; // The actual type
+ ClassMeta<?> gType; // The generic type
+
+ aType = session.push(attrName, o, eType);
+ boolean isRecursion = aType == null;
+
+ // Handle recursion
+ if (aType == null) {
+ o = null;
+ aType = object();
+ }
+
+ gType = aType.getTransformedClassMeta();
+ addClassAttr = (session.isAddClassAttrs() && ! eType.equals(aType));
+
+ // Transform if necessary
+ PojoTransform transform = aType.getPojoTransform(); // The transform
+ if (transform != null) {
+ o = transform.transform(o);
+
+ // If the transform's getTransformedClass() method returns Object, we need to figure out
+ // the actual type now.
+ if (gType.isObject())
+ gType = bc.getClassMetaForObject(o);
+ }
+
+ // '\0' characters are considered null.
+ if (o == null || (gType.isChar() && ((Character)o).charValue() == 0))
+ out.appendNull();
+ else if (gType.isBoolean())
+ out.appendBoolean((Boolean)o);
+ else if (gType.isNumber())
+ out.appendNumber((Number)o);
+ else if (gType.hasToObjectMapMethod())
+ serializeMap(session, out, gType.toObjectMap(o), gType);
+ else if (gType.isBean())
+ serializeBeanMap(session, out, bc.forBean(o), addClassAttr);
+ else if (gType.isUri() || (pMeta != null && (pMeta.isUri() || pMeta.isBeanUri())))
+ out.appendString(session.resolveUri(o.toString()));
+ else if (gType.isMap()) {
+ if (o instanceof BeanMap)
+ serializeBeanMap(session, out, (BeanMap)o, addClassAttr);
+ else
+ serializeMap(session, out, (Map)o, eType);
+ }
+ else if (gType.isCollection()) {
+ if (addClassAttr)
+ serializeCollectionMap(session, out, (Collection)o, gType);
+ else
+ serializeCollection(session, out, (Collection) o, eType);
+ }
+ else if (gType.isArray()) {
+ if (addClassAttr)
+ serializeCollectionMap(session, out, toList(gType.getInnerClass(), o), gType);
+ else
+ serializeCollection(session, out, toList(gType.getInnerClass(), o), eType);
+ } else
+ out.appendString(session.toString(o));
+
+ if (! isRecursion)
+ session.pop();
+ return out;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private void serializeMap(MsgPackSerializerSession session, MsgPackOutputStream out, Map m, ClassMeta<?> type) throws Exception {
+
+ ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType();
+
+ m = session.sort(m);
+
+ // The map size may change as we're iterating over it, so
+ // grab a snapshot of the entries in a separate list.
+ List<SimpleMapEntry> entries = new ArrayList<SimpleMapEntry>(m.size());
+ for (Map.Entry e : (Set<Map.Entry>)m.entrySet())
+ entries.add(new SimpleMapEntry(e.getKey(), e.getValue()));
+
+ out.startMap(entries.size());
+
+ for (SimpleMapEntry e : entries) {
+ Object value = e.value;
+ Object key = session.generalize(e.key, keyType);
+
+ serializeAnything(session, out, key, keyType, null, null);
+ serializeAnything(session, out, value, valueType, null, null);
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private void serializeCollectionMap(MsgPackSerializerSession session, MsgPackOutputStream out, Collection o, ClassMeta<?> type) throws Exception {
+
+ out.startMap(2);
+ serializeAnything(session, out, "_class", null, null, null);
+ serializeAnything(session, out, type.getInnerClass().getName(), null, null, null);
+ serializeAnything(session, out, "items", null, null, null);
+ serializeCollection(session, out, o, type);
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private void serializeBeanMap(MsgPackSerializerSession session, MsgPackOutputStream out, final BeanMap<?> m, boolean addClassAttr) throws Exception {
+
+ List<BeanPropertyValue> values = m.getValues(addClassAttr, session.isTrimNulls());
+
+ int size = values.size();
+ for (BeanPropertyValue p : values)
+ if (p.getThrown() != null)
+ size--;
+ out.startMap(size);
+
+ for (BeanPropertyValue p : values) {
+ BeanPropertyMeta pMeta = p.getMeta();
+ String key = p.getName();
+ Object value = p.getValue();
+ Throwable t = p.getThrown();
+ if (t != null)
+ session.addBeanGetterWarning(pMeta, t);
+ else {
+ serializeAnything(session, out, key, null, null, null);
+ serializeAnything(session, out, value, pMeta == null ? session.getBeanContext().string() : pMeta.getClassMeta(), key, pMeta);
+ }
+ }
+ }
+
+ private static class SimpleMapEntry {
+ final Object key;
+ final Object value;
+
+ private SimpleMapEntry(Object key, Object value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private void serializeCollection(MsgPackSerializerSession session, MsgPackOutputStream out, Collection c, ClassMeta<?> type) throws Exception {
+
+ ClassMeta<?> elementType = type.getElementType();
+ List<Object> l = new ArrayList<Object>(c.size());
+
+ c = session.sort(c);
+ l.addAll(c);
+
+ out.startArray(l.size());
+
+ for (Object o : l)
+ serializeAnything(session, out, o, elementType, "<iterator>", null);
+ }
+
+
+ //--------------------------------------------------------------------------------
+ // Overridden methods
+ //--------------------------------------------------------------------------------
+
+ @Override /* Serializer */
+ public MsgPackSerializerSession createSession(Object output, ObjectMap properties, Method javaMethod) {
+ return new MsgPackSerializerSession(getContext(MsgPackSerializerContext.class), getBeanContext(), output, properties, javaMethod);
+ }
+
+ @Override /* Serializer */
+ protected void doSerialize(SerializerSession session, Object o) throws Exception {
+ MsgPackSerializerSession s = (MsgPackSerializerSession)session;
+ serializeAnything(s, s.getOutputStream(), o, null, "root", null);
+ }
+
+ @Override /* CoreApi */
+ public MsgPackSerializer setProperty(String property, Object value) throws LockedException {
+ super.setProperty(property, value);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackSerializer setProperties(ObjectMap properties) throws LockedException {
+ super.setProperties(properties);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackSerializer addNotBeanClasses(Class<?>...classes) throws LockedException {
+ super.addNotBeanClasses(classes);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackSerializer addTransforms(Class<?>...classes) throws LockedException {
+ super.addTransforms(classes);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public <T> MsgPackSerializer addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+ super.addImplClass(interfaceClass, implClass);
+ return this;
+ }
+
+ @Override /* CoreApi */
+ public MsgPackSerializer setClassLoader(ClassLoader classLoader) throws LockedException {
+ super.setClassLoader(classLoader);
+ return this;
+ }
+
+ @Override /* Lockable */
+ public MsgPackSerializer lock() {
+ super.lock();
+ return this;
+ }
+
+ @Override /* Lockable */
+ public MsgPackSerializer clone() {
+ try {
+ MsgPackSerializer c = (MsgPackSerializer)super.clone();
+ return c;
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e); // Shouldn't happen
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerContext.java
new file mode 100644
index 0000000..49638b2
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerContext.java
@@ -0,0 +1,49 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Configurable properties on the {@link MsgPackSerializer} class.
+ * <p>
+ * Context properties are set by calling {@link ContextFactory#setProperty(String, Object)} on the context factory
+ * returned {@link CoreApi#getContextFactory()}.
+ * <p>
+ * The following convenience methods are also provided for setting context properties:
+ * <ul>
+ * <li>{@link MsgPackSerializer#setProperty(String,Object)}
+ * <li>{@link MsgPackSerializer#setProperties(ObjectMap)}
+ * <li>{@link MsgPackSerializer#addNotBeanClasses(Class[])}
+ * <li>{@link MsgPackSerializer#addTransforms(Class[])}
+ * <li>{@link MsgPackSerializer#addImplClass(Class,Class)}
+ * </ul>
+ * <p>
+ * See {@link ContextFactory} for more information about context properties.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackSerializerContext extends SerializerContext {
+
+ /**
+ * Constructor.
+ * <p>
+ * Typically only called from {@link ContextFactory#getContext(Class)}.
+ *
+ * @param cf The factory that created this context.
+ */
+ public MsgPackSerializerContext(ContextFactory cf) {
+ super(cf);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
new file mode 100644
index 0000000..a1709d9
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -0,0 +1,52 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.msgpack;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link MsgPackSerializer}.
+ * <p>
+ * This class is NOT thread safe. It is meant to be discarded after one-time use.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class MsgPackSerializerSession extends SerializerSession {
+
+ /**
+ * Create a new session using properties specified in the context.
+ *
+ * @param ctx The context creating this session object.
+ * The context contains all the configuration settings for this object.
+ * @param beanContext The bean context being used.
+ * @param output The output object. See {@link JsonSerializerSession#getOutputStream()} for valid class types.
+ * @param op The override properties.
+ * These override any context properties defined in the context.
+ * @param javaMethod The java method that called this parser, usually the method in a REST servlet.
+ */
+ protected MsgPackSerializerSession(MsgPackSerializerContext ctx, BeanContext beanContext, Object output, ObjectMap op, Method javaMethod) {
+ super(ctx, beanContext, output, op, javaMethod);
+ }
+
+ @Override
+ public MsgPackOutputStream getOutputStream() throws Exception {
+ Object output = getOutput();
+ if (output instanceof MsgPackOutputStream)
+ return (MsgPackOutputStream)output;
+ return new MsgPackOutputStream(super.getOutputStream());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/msgpack/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/package.html b/juneau-core/src/main/java/org/apache/juneau/msgpack/package.html
new file mode 100644
index 0000000..d37c0ac
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/package.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ /* For viewing in Page Designer */
+ @IMPORT url("../../../../../../javadoc.css");
+
+ /* For viewing in REST interface */
+ @IMPORT url("../htdocs/javadoc.css");
+ body {
+ margin: 20px;
+ }
+ </style>
+ <script>
+ /* Replace all @code and @link tags. */
+ window.onload = function() {
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+ }
+ </script>
+</head>
+<body>
+<p>JSON serialization and parsing support</p>
+<script>
+ function toggle(x) {
+ var div = x.nextSibling;
+ while (div != null && div.nodeType != 1)
+ div = div.nextSibling;
+ if (div != null) {
+ var d = div.style.display;
+ if (d == 'block' || d == '') {
+ div.style.display = 'none';
+ x.className += " closed";
+ } else {
+ div.style.display = 'block';
+ x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+ }
+ }
+ }
+</script>
+
+<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<ol class='toc'>
+</ol>
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/package.html b/juneau-core/src/main/java/org/apache/juneau/package.html
new file mode 100644
index 0000000..8b3d585
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/package.html
@@ -0,0 +1,217 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ /* For viewing in Page Designer */
+ @IMPORT url("../../../../../javadoc.css");
+
+ /* For viewing in REST interface */
+ @IMPORT url("../htdocs/javadoc.css");
+ body {
+ margin: 20px;
+ }
+ </style>
+ <script>
+ /* Replace all @code and @link tags. */
+ window.onload = function() {
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+ }
+ </script>
+</head>
+<body>
+<p>Base toolkit for serializers, parsers, and bean contexts</p>
+
+<script>
+ function toggle(x) {
+ var div = x.nextSibling;
+ while (div != null && div.nodeType != 1)
+ div = div.nextSibling;
+ if (div != null) {
+ var d = div.style.display;
+ if (d == 'block' || d == '') {
+ div.style.display = 'none';
+ x.className += " closed";
+ } else {
+ div.style.display = 'block';
+ x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+ }
+ }
+ }
+</script>
+
+<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<ol class='toc'>
+ <li><p><a class='doclink' href='#BeanContext_Api'>Bean Context API</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#BeanMap'>The BeanMap class</a></p>
+ <li><p><a class='doclink' href='#BeanContext'>The BeanContext class</a></p>
+ <li><p><a class='doclink' href='#Bean'>Bean annotations</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#ObjectMap_ObjectList'>ObjectMap and ObjectList APIs</a></p>
+ <li><p><a class='doclink' href='#PojoCategories'>POJO Categories</a></p>
+</ol>
+
+<!-- ======================================================================================================== -->
+<a id="BeanContext_Api"></a>
+<h2 class='topic' onclick='toggle(this)'>1 - Bean Context API</h2>
+<div class='topic'>
+ <p>
+ The {@link org.apache.juneau.BeanContext} class is the core class in the Juneau architecture. It serves multiple functions...
+ </p>
+ <ul class='normal'>
+ <li>It provides the ability to create instances of {@link org.apache.juneau.BeanMap BeanMaps}.
+ <li>It serves as a repository for {@link org.apache.juneau.transform.Transform Transforms}, which are used to tailor how beans and non-beans are handled.
+ <li>It's used by all built-in {@link org.apache.juneau.serializer.Serializer Serializers} and {@link org.apache.juneau.parser.Parser Parsers} for working with POJOs in a consistent way.
+ </ul>
+
+ <!-- ======================================================================================================== -->
+ <a id="BeanMap"></a>
+ <h3 class='topic' onclick='toggle(this)'>1.1 - The BeanMap class</h3>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.BeanMap} class allows you to access the properties of a bean through the familiar {@code Map} interface.
+ So, for example, you can use the {@code Map.get(key)} method to retrieve a property value in leu of it's getter method, and the {@code Map.put(key, value)} method to set a property value in leu of it's setter method.
+ </p>
+ <p>
+ The serialization and parsing of beans in Juneau is accomplished by wrapping Java beans inside instances of the class {@code BeanMap}.
+ </p>
+ <p>
+ <b>Note:</b> Instances of {@link org.apache.juneau.BeanMap} objects are always retrieved through the {@link org.apache.juneau.BeanContext} class. You cannot instantiate {@code BeanMaps} directly since the rules for defining what constitutes a bean depend on various settings in the bean context.
+ </p>
+ <p>
+ In general, the performance on using the {@link org.apache.juneau.BeanMap} class to access properties is equivalent to using reflection directly.
+ </p>
+ <p>
+ See the {@link org.apache.juneau.BeanMap} javadoc for more information.
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="BeanContext"></a>
+ <h3 class='topic' onclick='toggle(this)'>1.2 - The BeanContext class</h3>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.BeanContext} class is the workhorse class used to wrap Java beans inside {@link org.apache.juneau.BeanMap BeanMaps}.
+ There are several options provided on the {@link org.apache.juneau.BeanContext} class to tailor the definition of a bean.
+ </p>
+ <p>
+ The following is a very simple example of how to wrap a bean inside a {@link org.apache.juneau.BeanMap} wrapper and use the wrapper interface to get and set property values on the bean.
+ In this case, we're using the DEFAULT bean context.
+ </p>
+ <p class='bcode'>
+ <jc>// A sample pseudo bean class.</jc>
+ <jk>public class</jk> Person {
+ <jk>public</jk> String getName();
+ <jk>public void</jk> setName(String name);
+ <jk>public int</jk> getAge();
+ <jk>public void</jk> setAge(<jk>int</jk> age);
+ }
+
+ <jc>// Get an instance of a bean context.
+ // In this case, just use the default bean context.</jc>
+ BeanContext beanContext = BeanContext.<jsf>DEFAULT</jsf>;
+
+ <jc>// Create an instance of our bean and wrap it in a bean map.</jc>
+ Person p = <jk>new</jk> Person();
+ BeanMap<Person> m = beanContext.forBean(p);
+
+ <jc>// Set some properties on the bean.</jc>
+ m.put(<js>"name"</js>, <js>"John Smith"</js>);
+ m.put(<js>"age"</js>, 21);
+
+ <jc>// Print out bean properties.</jc>
+ System.out.println(m.get(<js>"name"</js>)); <jc>// Prints "John Smith"</jc>
+ System.out.println(p.getName()); <jc>// Prints "John Smith"</jc>
+ System.out.println(m.get(<js>"age"</js>)); <jc>// Prints 21</jc>
+ System.out.println(p.getAge()); <jc>// Prints 21</jc>
+
+ <jc>// The bean context class can also create instances of bean maps.</jc>
+ m = beanContext.newBeanMap(Person.<jk>class</jk>);
+ p = m.getBean(); <jc>// Get the new wrapped bean.</jc>
+
+ <jc>// The bean context class can also create instances of beans.</jc>
+ p = beanContext.newBean(Person.<jk>class</jk>);
+ </p>
+ <p>
+ There are 3 ways to get an instance of a {@link org.apache.juneau.BeanContext}:
+ </p>
+ <p class='bcode'>
+ <jc>// Use one of the default bean contexts.</jc>
+ BeanContext beanContext = BeanContext.<jsf>DEFAULT</jsf>;
+
+ <jc>// Create a context from scratch with your own settings.</jc>
+ beanContext = <jk>new</jk> BeanContext().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+
+ <jc>// Clone and modify an existing context.</jc>
+ beanContext = BeanContext.<jsf>DEFAULT</jsf>.clone().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+ </p>
+ <p>
+ The {@link org.apache.juneau.BeanContext} class is a highly-customizable class.
+ See the {@link org.apache.juneau.BeanContext} javadoc for more information.
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="Bean"></a>
+ <h3 class='topic' onclick='toggle(this)'>1.3 - Bean annotations</h3>
+ <div class='topic'>
+ <p>
+ Juneau provides the following annotations that can be used to fine-tune what properties are associated with beans:
+ </p>
+ <ul class='normal'>
+ <li>{@link org.apache.juneau.annotation.Bean} - Fine-tune properties associated with beans.
+ <li>{@link org.apache.juneau.annotation.BeanProperty} - Fine-tune bean properties (fields / getters / setters).
+ <li>{@link org.apache.juneau.annotation.BeanConstructor} - Define read-only bean properties that can only be set through constructor arguments.
+ <li>{@link org.apache.juneau.annotation.BeanIgnore} - Prevent bean classes/methods/fields from being interpreted as bean constructs.
+ </ul>
+ <p>
+ These annotations always override the settings defined in the {@link org.apache.juneau.BeanContext} class.
+ </p>
+ <p>
+ For example, the following bean class will only have one property associated with it, <js>"name"</js>, since it's the only one listed in the list of properties.
+ </p>
+ <p class='bcode'>
+ <jc>// Bean with only one 'name' property</jc>
+ <ja>@Bean</ja>(properties={<js>"name"</js>})
+ <jk>public class</jk> Person {
+ <jk>public</jk> String getName();
+ <jk>public void</jk> setName(String name);
+ <jk>public int</jk> getAge();
+ <jk>public void</jk> setAge(<jk>int</jk> age);
+ }
+ </p>
+ <p>
+ When this bean is serialized using one of the {@link org.apache.juneau.serializer.Serializer Serializers}, the age property will be ignored.
+ </p>
+ <p>
+ Using the <ja>@Bean</ja> and <ja>@BeanProperty</ja> annotations, it's also possible to include non-standard properties (for example, getters or setters with non-standard names), or override the names of properties (for example, {@code "Name"} or {@code "fullName"} instead of {@code "name"}).
+ </p>
+ <p>
+ It should be noted that the {@link org.apache.juneau.transform.BeanTransform} class can also be used to exclude properties from beans.
+ However, only the annotations can be used to include non-standard properties or override property names.
+ </p>
+ <p>
+ See the {@link org.apache.juneau.annotation.Bean}, {@link org.apache.juneau.annotation.BeanProperty}, {@link org.apache.juneau.annotation.BeanConstructor}, and {@link org.apache.juneau.annotation.BeanIgnore} javadocs for more information.
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/parser/InputStreamParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-core/src/main/java/org/apache/juneau/parser/InputStreamParser.java
new file mode 100644
index 0000000..ac8237c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/InputStreamParser.java
@@ -0,0 +1,45 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.parser;
+
+import org.apache.juneau.annotation.*;
+
+/**
+ * Subclass of {@link Parser} for byte-based parsers.
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * This class is typically the parent class of all byte-based parsers.
+ * It has 1 abstract method to implement...
+ * <ul>
+ * <li><code>parse(InputStream, ClassMeta, ParserContext)</code>
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>@Consumes annotation</h6>
+ * <p>
+ * The media types that this parser can handle is specified through the {@link Consumes @Consumes} annotation.
+ * <p>
+ * However, the media types can also be specified programmatically by overriding the {@link #getMediaTypes()} method.
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public abstract class InputStreamParser extends Parser {
+
+ @Override /* Parser */
+ public boolean isReaderParser() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/parser/ParseException.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParseException.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParseException.java
new file mode 100644
index 0000000..08e2508
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParseException.java
@@ -0,0 +1,105 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF 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.apache.juneau.parser;
+
+import java.text.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+
+/**
+ * Exception that indicates invalid syntax encountered during parsing.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class ParseException extends FormattedException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param session The parser session to extract information from.
+ * @param message The exception message containing {@link MessageFormat}-style arguments.
+ * @param args Message arguments.
+ */
+ public ParseException(ParserSession session, String message, Object...args) {
+ super(getMessage(session, message, args));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The exception message containing {@link MessageFormat}-style arguments.
+ * @param args Message arguments.
+ */
+ public ParseException(String message, Object...args) {
+ super(getMessage(null, message, args));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param session The parser session to extract information from.
+ * @param causedBy The inner exception.
+ */
+ public ParseException(ParserSession session, Exception causedBy) {
+ super(causedBy, getMessage(session, causedBy.getMessage()));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param causedBy The inner exception.
+ */
+ public ParseException(Exception causedBy) {
+ super(causedBy, getMessage(null, causedBy.getMessage()));
+ }
+
+ private static String getMessage(ParserSession session, String msg, Object... args) {
+ if (args.length != 0)
+ msg = MessageFormat.format(msg, args);
+ if (session != null) {
+ Map<String,Object> m = session.getLastLocation();
+ if (m != null && ! m.isEmpty())
+ msg = "Parse exception occurred at " + JsonSerializer.DEFAULT_LAX.toString(m) + ". " + msg;
+ }
+ return msg;
+ }
+
+ /**
+ * Returns the highest-level <code>ParseException</code> in the stack trace.
+ * Useful for JUnit testing of error conditions.
+ *
+ * @return The root parse exception, or this exception if there isn't one.
+ */
+ public ParseException getRootCause() {
+ ParseException t = this;
+ while (! (t.getCause() == null || ! (t.getCause() instanceof ParseException)))
+ t = (ParseException)t.getCause();
+ return t;
+ }
+
+ /**
+ * Sets the inner cause for this exception.
+ *
+ * @param cause The inner cause.
+ * @return This object (for method chaining).
+ */
+ @Override /* Throwable */
+ public synchronized ParseException initCause(Throwable cause) {
+ super.initCause(cause);
+ return this;
+ }
+}