You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pl...@apache.org on 2016/02/19 08:43:07 UTC

directory-kerby git commit: DIRKRB-532 Encode and decode XDR: Union and Struct. Contributed by Yan.

Repository: directory-kerby
Updated Branches:
  refs/heads/kadmin-remote 1765f8281 -> 8188a1277


DIRKRB-532 Encode and decode XDR: Union and Struct. Contributed by Yan.


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/8188a127
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/8188a127
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/8188a127

Branch: refs/heads/kadmin-remote
Commit: 8188a12774fb231576b09b8424337d9b1df12d09
Parents: 1765f82
Author: plusplusjiajia <ji...@intel.com>
Authored: Fri Feb 19 15:48:36 2016 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Fri Feb 19 15:48:36 2016 +0800

----------------------------------------------------------------------
 .../java/org/apache/kerby/xdr/XdrDataType.java  |   4 +-
 .../java/org/apache/kerby/xdr/XdrFieldInfo.java |  30 +++-
 .../org/apache/kerby/xdr/type/XdrBoolean.java   |   6 +
 .../apache/kerby/xdr/type/XdrEnumerated.java    |   4 +
 .../org/apache/kerby/xdr/type/XdrInteger.java   |   4 +
 .../org/apache/kerby/xdr/type/XdrSimple.java    |   2 +
 .../org/apache/kerby/xdr/type/XdrString.java    |  18 +-
 .../apache/kerby/xdr/type/XdrStructType.java    |  42 ++++-
 .../org/apache/kerby/xdr/type/XdrUnion.java     | 131 ++++++++++++++
 .../kerby/xdr/type/XdrUnsignedInteger.java      |   5 +
 .../apache/kerby/xdr/XdrEnumeratedInstance.java |   2 +-
 .../org/apache/kerby/xdr/XdrStringTest.java     |   5 +-
 .../apache/kerby/xdr/XdrStructTypeInstance.java | 112 ++++++++++++
 .../org/apache/kerby/xdr/XdrStructTypeTest.java |  83 +++++++++
 .../org/apache/kerby/xdr/XdrUnionInstance.java  | 170 +++++++++++++++++++
 .../java/org/apache/kerby/xdr/XdrUnionTest.java |  67 ++++++++
 16 files changed, 662 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrDataType.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrDataType.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrDataType.java
index 57396e3..7b2d244 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrDataType.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrDataType.java
@@ -32,7 +32,9 @@ public enum XdrDataType {
     STRING              (0X04),
     ENUM                (0x05),
     OPAQUE              (0x06),
-    UNSIGNED_INTEGER   (0x07);
+    UNSIGNED_INTEGER   (0x07),
+    STRUCT               (0x08),
+    UNION                (0x09);
 
     /** The dataType value */
     private int value;

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrFieldInfo.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrFieldInfo.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrFieldInfo.java
index eece615..7804701 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrFieldInfo.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/XdrFieldInfo.java
@@ -19,27 +19,41 @@
  */
 package org.apache.kerby.xdr;
 
-import org.apache.kerby.xdr.type.XdrType;
-
 /**
  * Representing a field in a XDR struct.
  */
 public class XdrFieldInfo {
-    private EnumType index;
-    private Class<? extends XdrType> type;
+    private int index;
+    //private Class<? extends XdrType> type;
+    private XdrDataType dataType;
+    private Object value;
 
     /**
      * Constructor.
      * @param index
-     * @param type
+     * @param dataType
+     *
      */
-    public XdrFieldInfo(EnumType index, Class<? extends XdrType> type) {
+    public XdrFieldInfo(int index, XdrDataType dataType, Object value) {//Class<? extends XdrType> type
         this.index = index;
-        this.type = type;
+        //this.type = type;
+        this.dataType = dataType;
+        this.value = value;
     }
 
-    public EnumType getIndex() {
+    public int getIndex() {
         return index;
     }
 
+    //public Class<? extends XdrType> getTypeClass() {
+        //return type;
+    //}
+
+    public XdrDataType getDataType() {
+        return dataType;
+    }
+
+    public Object getValue() {
+        return value;
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrBoolean.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrBoolean.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrBoolean.java
index 8ed8e91..224b681 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrBoolean.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrBoolean.java
@@ -22,6 +22,7 @@ package org.apache.kerby.xdr.type;
 import org.apache.kerby.xdr.XdrDataType;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 
 /**
@@ -73,6 +74,11 @@ public class XdrBoolean extends XdrSimple<Boolean> {
      */
     @Override
     protected void toValue() throws IOException {
+        if (getBytes().length != 4) {
+            byte[] boolBytes = ByteBuffer.allocate(4).put(getBytes(), 0, 4).array();
+            setBytes(boolBytes); /**reset bytes in case the enum type is in a struct or union*/
+        }
+
         byte[] bytes = getBytes();
         if (Arrays.equals(bytes, TRUE_BYTE)) {
             setValue(true);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrEnumerated.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrEnumerated.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrEnumerated.java
index 5193ef2..463e626 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrEnumerated.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrEnumerated.java
@@ -47,6 +47,10 @@ public abstract class XdrEnumerated<T extends EnumType> extends XdrSimple<T> {
     }
 
     protected void toValue() {
+        if (getBytes().length != 4) {
+            byte[] intBytes = ByteBuffer.allocate(4).put(getBytes(), 0, 4).array();
+            setBytes(intBytes); /**reset bytes in case the enum type is in a struct or union*/
+        }
         BigInteger biVal = new BigInteger(getBytes());
         int iVal = biVal.intValue();
         EnumType[] allValues = getAllEnumValues();

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrInteger.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrInteger.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrInteger.java
index 3835933..4e78870 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrInteger.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrInteger.java
@@ -73,6 +73,10 @@ public class XdrInteger extends XdrSimple<Integer> {
      */
     @Override
     protected void toValue() {
+        if (getBytes().length != 4) {
+            byte[] intBytes = ByteBuffer.allocate(4).put(getBytes(), 0, 4).array();
+            setBytes(intBytes); /**reset bytes in case the enum type is in a struct or union*/
+        }
         ByteBuffer buffer = ByteBuffer.wrap(getBytes());
         setValue(buffer.getInt());
     }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrSimple.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrSimple.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrSimple.java
index 89427d9..b2eccb1 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrSimple.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrSimple.java
@@ -118,6 +118,8 @@ public abstract class XdrSimple<T> extends AbstractXdrType<T> {
         switch (dataType) {
             case BOOLEAN:
             case INTEGER:
+            case UNSIGNED_INTEGER:
+            case ENUM:
             case STRING:
                 return true;
             default:

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrString.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrString.java
index 26ec37c..145e48d 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrString.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrString.java
@@ -43,12 +43,12 @@ import java.util.List;
 public class XdrString extends XdrSimple<String> {
     private int padding;
 
-    public XdrString(XdrDataType xdrDataType) {
-        super(xdrDataType, null);
+    public XdrString() {
+        this((String) null);
     }
 
-    public XdrString(XdrDataType dataTypeNo, String value) {
-        super(dataTypeNo, value);
+    public XdrString(String value) {
+        super(XdrDataType.STRING, value);
     }
 
     @Override
@@ -68,7 +68,7 @@ public class XdrString extends XdrSimple<String> {
     @Override
     protected int encodingBodyLength() {
         if (getValue() != null) {
-            padding = 4 - getValue().length() % 4;
+            padding = (4 - getValue().length() % 4) % 4;
             return getValue().length() + padding + 4;
         }
         return 0;
@@ -79,10 +79,16 @@ public class XdrString extends XdrSimple<String> {
         byte[] header = new byte[4];
         System.arraycopy(bytes, 0, header, 0, 4);
         int StringLen  = ByteBuffer.wrap(header).getInt();
-        int paddingBytes = bytes.length - StringLen - 4;
+        int paddingBytes = (4 - (StringLen % 4)) % 4;
         validatePaddingBytes(paddingBytes);
         setPadding(paddingBytes);
 
+        if (bytes.length != StringLen + 4 + paddingBytes) {
+            int totalLength = StringLen + paddingBytes + 4;
+            byte[] StringBytes = ByteBuffer.allocate(totalLength).put(getBytes(), 0, totalLength).array();
+            setBytes(StringBytes); /**reset bytes in case the enum type is in a struct or union*/
+        }
+
         byte[] content = new byte[StringLen];
         if (bytes.length > 1) {
             System.arraycopy(bytes, 4, content, 0, StringLen);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrStructType.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrStructType.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrStructType.java
index bea0788..6bb74a5 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrStructType.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrStructType.java
@@ -29,16 +29,28 @@ import java.nio.ByteBuffer;
  * For collection type that may consist of dataTypeged fields
  */
 public abstract class XdrStructType extends AbstractXdrType<XdrStructType> {
-    private final XdrFieldInfo[] fieldInfos;
-    private final XdrType[] fields;
+    private XdrFieldInfo[] fieldInfos;
+    private XdrType[] fields;
+
+    public XdrStructType(XdrDataType xdrDataType) {
+        super(xdrDataType);
+        this.fieldInfos = null;
+        this.fields = null;
+    }
 
     public XdrStructType(XdrDataType xdrDataType,
                          final XdrFieldInfo[] fieldInfos) {
         super(xdrDataType);
-
-        setValue(this);
         this.fieldInfos = fieldInfos;
         this.fields = new XdrType[fieldInfos.length];
+
+        getStructTypeInstance(this.fields, fieldInfos);
+    }
+
+    protected abstract void getStructTypeInstance(final XdrType[] fields, final XdrFieldInfo[] fieldInfos);
+
+    public XdrFieldInfo[] getXdrFieldInfos() {
+        return fieldInfos;
     }
 
     @Override
@@ -62,4 +74,26 @@ public abstract class XdrStructType extends AbstractXdrType<XdrStructType> {
             }
         }
     }
+
+    @Override
+    public void decode(ByteBuffer content) throws IOException {
+        AbstractXdrType[] fields = getAllFields();
+        Object[] value;
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i] != null) {
+                fields[i].decode(content);
+                int length = fields[i].encodingLength();
+                byte[] array = content.array();
+                byte[] newArray = new byte[array.length - length];
+                System.arraycopy(array, length, newArray, 0, array.length - length);
+                content = ByteBuffer.wrap(newArray);
+            }
+        }
+        this.fields = fields;
+        setValue(fieldsToValues(fields));
+    }
+
+    protected abstract XdrStructType fieldsToValues(AbstractXdrType[] fields);
+
+    protected abstract AbstractXdrType[] getAllFields();
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnion.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnion.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnion.java
new file mode 100644
index 0000000..2210669
--- /dev/null
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnion.java
@@ -0,0 +1,131 @@
+/**
+ *  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.kerby.xdr.type;
+
+import org.apache.kerby.xdr.XdrDataType;
+import org.apache.kerby.xdr.XdrFieldInfo;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * A discriminated union is a type composed of a discriminant followed
+ * by a type selected from a set of prearranged types according to the
+ * value of the discriminant.  The type of discriminant is either "int",
+ * "unsigned int", or an enumerated type, such as "bool".  The component
+ * types are called "arms" of the union and are preceded by the value of
+ * the discriminant that implies their encoding.  Discriminated unions
+ * are declared as follows:
+ *
+ *  union switch (discriminant-declaration) {
+ *      case discriminant-value-A:
+ *          arm-declaration-A;
+ *      case discriminant-value-B:
+ *          arm-declaration-B;
+ *      ...
+ *      default: default-declaration;
+ *  } identifier;
+ * Each "case" keyword is followed by a legal value of the discriminant.
+ * The default arm is optional.  If it is not specified, then a valid
+ * encoding of the union cannot take on unspecified discriminant values.
+ * The size of the implied arm is always a multiple of four bytes.
+ *
+ * The discriminated union is encoded as its discriminant followed by
+ * the encoding of the implied arm.
+ *                  0   1   2   3
+ *                  +---+---+---+---+---+---+---+---+
+ *                  |  discriminant |  implied arm  |
+ *                  +---+---+---+---+---+---+---+---+
+ *                  |<---4 bytes--->|
+ */
+public abstract class XdrUnion extends AbstractXdrType<XdrUnion> {
+    /**
+     * [0] is the discriminant
+     *      index, XdrDataType, value;
+     * [1] is the implied arm
+     */
+    private XdrFieldInfo[] fieldInfos;
+    private XdrType[] fields;
+
+    public XdrUnion(XdrDataType xdrDataType) {
+        super(xdrDataType);
+        this.fieldInfos = null;
+        this.fields = null;
+    }
+
+    public XdrUnion(XdrDataType xdrDataType,
+                         final XdrFieldInfo[] fieldInfos) {
+        super(xdrDataType);
+        this.fieldInfos = fieldInfos;
+        this.fields = new XdrType[fieldInfos.length];
+
+        getUnionInstance(this.fields, fieldInfos);
+    }
+
+    protected abstract void getUnionInstance(final XdrType[] fields, final XdrFieldInfo[] fieldInfos);
+
+    public XdrFieldInfo[] getXdrFieldInfos() {
+        return fieldInfos;
+    }
+
+    @Override
+    protected int encodingBodyLength() throws IOException {
+        int allLen = 0;
+        for (int i = 0; i < fields.length; i++) {
+            AbstractXdrType field = (AbstractXdrType) fields[i];
+            if (field != null) {
+                allLen += field.encodingLength();
+            }
+        }
+        return allLen;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
+        for (int i = 0; i < fields.length; ++i) {
+            XdrType field = fields[i];
+            if (field != null) {
+                field.encode(buffer);
+            }
+        }
+    }
+
+    @Override
+    public void decode(ByteBuffer content) throws IOException {
+        AbstractXdrType[] fields = getAllFields();
+        Object[] value;
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i] != null) {
+                fields[i].decode(content);
+                int length = fields[i].encodingLength();
+                byte[] array = content.array();
+                byte[] newArray = new byte[array.length - length];
+                System.arraycopy(array, length, newArray, 0, array.length - length);
+                content = ByteBuffer.wrap(newArray);
+            }
+        }
+        this.fields = fields;
+        setValue(fieldsToValues(fields));
+    }
+
+    protected abstract XdrUnion fieldsToValues(AbstractXdrType[] fields);
+
+    protected abstract AbstractXdrType[] getAllFields();
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnsignedInteger.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnsignedInteger.java b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnsignedInteger.java
index 70044f9..cfd7ed3 100644
--- a/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnsignedInteger.java
+++ b/kerby-common/kerby-xdr/src/main/java/org/apache/kerby/xdr/type/XdrUnsignedInteger.java
@@ -86,6 +86,11 @@ public class XdrUnsignedInteger extends XdrSimple<Long> {
      */
     @Override
     protected void toValue() {
+        if (getBytes().length != 4) {
+            byte[] Bytes = ByteBuffer.allocate(4).put(getBytes(), 0, 4).array();
+            setBytes(Bytes); /**reset bytes in case the enum type is in a struct or union*/
+        }
+
         byte[] longBytes = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
         System.arraycopy(getBytes(), 0, longBytes, 4, 4);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrEnumeratedInstance.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrEnumeratedInstance.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrEnumeratedInstance.java
index a0611d2..2c6a576 100644
--- a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrEnumeratedInstance.java
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrEnumeratedInstance.java
@@ -39,7 +39,7 @@ enum Color implements EnumType {
     }
 }
 
-public class XdrEnumeratedInstance  extends XdrEnumerated<Color> {
+public class XdrEnumeratedInstance extends XdrEnumerated<Color> {
 
     public XdrEnumeratedInstance() {
         super(null);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStringTest.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStringTest.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStringTest.java
index c799d5a..f09c6db 100644
--- a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStringTest.java
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStringTest.java
@@ -37,7 +37,7 @@ public class XdrStringTest {
 
         private void testEncodingWith(String value, String expectedEncoding) throws IOException {
             byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
-            XdrString aValue = new XdrString(XdrDataType.STRING, value);
+            XdrString aValue = new XdrString(value);
 
             byte[] encodingBytes = aValue.encode();
             assertThat(encodingBytes).isEqualTo(expected);
@@ -52,8 +52,7 @@ public class XdrStringTest {
         }
 
         private void testDecodingWith(String expectedValue, String content) throws IOException {
-            XdrString decoded = new XdrString(XdrDataType.STRING);
-
+            XdrString decoded = new XdrString();
             decoded.decode(HexUtil.hex2bytesFriendly(content));
             assertThat(decoded.getValue()).isEqualTo(expectedValue);
         }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeInstance.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeInstance.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeInstance.java
new file mode 100644
index 0000000..4e3106b
--- /dev/null
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeInstance.java
@@ -0,0 +1,112 @@
+/**
+ *  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.kerby.xdr;
+
+import org.apache.kerby.xdr.type.AbstractXdrType;
+import org.apache.kerby.xdr.type.XdrBoolean;
+import org.apache.kerby.xdr.type.XdrEnumerated;
+import org.apache.kerby.xdr.type.XdrInteger;
+import org.apache.kerby.xdr.type.XdrString;
+import org.apache.kerby.xdr.type.XdrStructType;
+import org.apache.kerby.xdr.type.XdrType;
+import org.apache.kerby.xdr.type.XdrUnion;
+import org.apache.kerby.xdr.type.XdrUnsignedInteger;
+
+class MyFile {
+    String fileName;
+    UnionFileTypeSwitch fileType;
+    String owner;
+
+    public MyFile(String name, UnionFileTypeSwitch fileType, String owner) {
+        this.fileName = name;
+        this.fileType = fileType;
+        this.owner = owner;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public UnionFileTypeSwitch getFileType() {
+        return fileType;
+    }
+
+    public String getOwner() {
+        return owner;
+    }
+
+}
+
+public class XdrStructTypeInstance extends XdrStructType {
+    public XdrStructTypeInstance() {
+        super(XdrDataType.STRUCT);
+    }
+
+    public XdrStructTypeInstance(XdrFieldInfo[] fieldInfos) {
+        super(XdrDataType.STRUCT, fieldInfos);
+    }
+
+    protected  void getStructTypeInstance(final XdrType[] fields, final XdrFieldInfo[] fieldInfos) {
+        for (int i = 0; i < fieldInfos.length; i++) {
+            switch (fieldInfos[i].getDataType()) {
+                case INTEGER:
+                    fields[i] = new XdrInteger((Integer) fieldInfos[i].getValue());
+                    break;
+                case UNSIGNED_INTEGER:
+                    fields[i] = new XdrUnsignedInteger((Long) fieldInfos[i].getValue());
+                    break;
+                case BOOLEAN:
+                    fields[i] = new XdrBoolean((Boolean) fieldInfos[i].getValue());
+                    break;
+                case ENUM:
+                    fields[i] = new FileKindEnumeratedInstance((FileKind) fieldInfos[i].getValue());
+                    break;
+                case UNION:
+                    fields[i] = (XdrUnion) fieldInfos[i].getValue();
+                    break;
+                case STRING:
+                    fields[i] = new XdrString((String) fieldInfos[i].getValue());
+                    break;
+                case STRUCT:
+                    fields[i] = new XdrStructTypeInstance((XdrFieldInfo[]) fieldInfos[i].getValue());
+                default:
+                    fields[i] = null;
+            }
+        }
+
+    }
+
+    @Override
+    protected XdrStructType fieldsToValues(AbstractXdrType[] fields) {
+        XdrFieldInfo[] fieldInfos = {new XdrFieldInfo(0, XdrDataType.STRING, fields[0].getValue()),
+                new XdrFieldInfo(1, XdrDataType.UNION,fields[1].getValue()),
+                new XdrFieldInfo(2, XdrDataType.STRING, fields[2].getValue())};
+        return new XdrStructTypeInstance(fieldInfos);
+    }
+
+    @Override
+    protected AbstractXdrType[] getAllFields() {
+        AbstractXdrType[] fields = new AbstractXdrType[3];
+        fields[0] = new XdrString();
+        fields[1] = new XdrUnionInstance();
+        fields[2] = new XdrString();
+        return fields;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeTest.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeTest.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeTest.java
new file mode 100644
index 0000000..2fba220
--- /dev/null
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrStructTypeTest.java
@@ -0,0 +1,83 @@
+/**
+ *  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.kerby.xdr;
+
+import org.apache.kerby.xdr.type.XdrStructType;
+import org.apache.kerby.xdr.type.XdrUnion;
+import org.apache.kerby.xdr.util.HexUtil;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class XdrStructTypeTest {
+    @Test
+    public void testEncoding() throws IOException {
+        MyFile file = new MyFile("sillyprog", new UnionFileTypeSwitch(FileKind.EXEC), "john");
+        testEncodingWith(file, "0x00 00 00 09 73 69 6c 6c 79 70 72 6f 67 00 00 00 00 00 00 02 " +
+                "00 00 00 04 6c 69 73 70 00 00 00 04 6a 6f 68 6e");
+    }
+
+    private void testEncodingWith(MyFile value, String expectedEncoding) throws IOException {
+        byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
+        UnionFileTypeSwitch fileType = value.getFileType();
+        XdrFieldInfo[] unionFieldInfo = {new XdrFieldInfo(0, fileType.getFileKind(), fileType.getFileValue()),
+                new XdrFieldInfo(1, fileType.getArmKind(), fileType.getArmValue())};
+        XdrFieldInfo[] fieldInfos = {new XdrFieldInfo(0, XdrDataType.STRING, value.getFileName()),
+                new XdrFieldInfo(1, XdrDataType.UNION, new XdrUnionInstance(unionFieldInfo)),
+                new XdrFieldInfo(2, XdrDataType.STRING, value.getOwner())};
+
+        XdrStructType aValue = new XdrStructTypeInstance(fieldInfos);
+
+        byte[] encodingBytes = aValue.encode();
+        assertThat(encodingBytes).isEqualTo(expected);
+    }
+
+
+    @Test
+    public void testDecoding() throws IOException {
+        MyFile file = new MyFile("sillyprog", new UnionFileTypeSwitch(FileKind.EXEC), "john");
+        testDecodingWith(file, "0x00 00 00 09 73 69 6c 6c 79 70 72 6f 67 00 00 00 00 00 00 02 " +
+                "00 00 00 04 6c 69 73 70 00 00 00 04 6a 6f 68 6e");
+    }
+
+    private void testDecodingWith(MyFile expectedValue, String content) throws IOException {
+        XdrStructType decoded = new XdrStructTypeInstance();
+
+        decoded.decode(HexUtil.hex2bytesFriendly(content));
+
+        XdrFieldInfo[] fieldInfos = decoded.getValue().getXdrFieldInfos();
+        assertThat(fieldInfos.length).isEqualTo(3);
+        assertThat(fieldInfos[0].getDataType()).isEqualTo(XdrDataType.STRING);
+        assertThat((String) fieldInfos[0].getValue()).isEqualTo(expectedValue.getFileName());
+
+        assertThat(fieldInfos[1].getDataType()).isEqualTo(XdrDataType.UNION);
+        XdrFieldInfo[] unionFieldInfo = ((XdrUnion) fieldInfos[1].getValue()).getXdrFieldInfos();
+        assertThat(unionFieldInfo[0].getDataType()).isEqualTo(expectedValue.getFileType().getFileKind());
+        assertThat(unionFieldInfo[0].getValue()).isEqualTo(expectedValue.getFileType().getFileValue());
+        assertThat(unionFieldInfo[1].getDataType()).isEqualTo(expectedValue.getFileType().getArmKind());
+        assertThat((String) unionFieldInfo[1].getValue()).isEqualTo(expectedValue.getFileType().getArmValue());
+
+        assertThat(fieldInfos[2].getDataType()).isEqualTo(XdrDataType.STRING);
+        assertThat((String) fieldInfos[2].getValue()).isEqualTo(expectedValue.getOwner());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionInstance.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionInstance.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionInstance.java
new file mode 100644
index 0000000..6f86ad9
--- /dev/null
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionInstance.java
@@ -0,0 +1,170 @@
+/**
+ *  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.kerby.xdr;
+
+import org.apache.kerby.xdr.type.AbstractXdrType;
+import org.apache.kerby.xdr.type.XdrBoolean;
+import org.apache.kerby.xdr.type.XdrEnumerated;
+import org.apache.kerby.xdr.type.XdrInteger;
+import org.apache.kerby.xdr.type.XdrString;
+import org.apache.kerby.xdr.type.XdrType;
+import org.apache.kerby.xdr.type.XdrUnion;
+import org.apache.kerby.xdr.type.XdrUnsignedInteger;
+
+enum FileKind implements EnumType {
+    TEXT,
+    DATA,
+    EXEC;
+
+    public int getValue() {
+        return ordinal();
+    }
+
+    public String getName() {
+        return name();
+    }
+}
+
+class FileKindEnumeratedInstance extends XdrEnumerated<FileKind> {
+
+    public FileKindEnumeratedInstance() {
+        super(null);
+    }
+
+    public FileKindEnumeratedInstance(FileKind value) {
+        super(value);
+    }
+    @Override
+    protected EnumType[] getAllEnumValues() {
+        return FileKind.values();
+    }
+
+}
+
+class UnionFileTypeSwitch {
+    FileKind fileKind;
+    Object arm;
+    public UnionFileTypeSwitch(FileKind fileKind) {
+        this.fileKind = fileKind;
+        switch (fileKind) {
+            case TEXT:
+                arm = null;
+                break;
+            case DATA:
+                arm = "creator";
+                break;
+            case EXEC:
+                arm = "lisp";
+                break;
+        }
+    }
+
+    XdrDataType getFileKind() {
+        return XdrDataType.ENUM;
+    }
+
+    FileKind getFileValue() {
+        return fileKind;
+    }
+
+    XdrDataType getArmKind() {
+        XdrDataType xdrDataType = XdrDataType.UNKNOWN;
+        switch (fileKind) {
+            case TEXT:
+                xdrDataType = XdrDataType.UNKNOWN;
+                break;
+            case DATA:
+                xdrDataType = XdrDataType.STRING;
+                break;
+            case EXEC:
+                xdrDataType = XdrDataType.STRING;
+                break;
+        }
+        return xdrDataType;
+    }
+
+    Object getArmValue() {
+        return arm;
+    }
+}
+
+public class XdrUnionInstance extends XdrUnion{
+
+    public XdrUnionInstance() {
+        super(XdrDataType.UNION);
+    }
+
+    public XdrUnionInstance(XdrFieldInfo[] fieldInfos) {
+        super(XdrDataType.UNION, fieldInfos);
+    }
+
+
+    @Override
+    protected void getUnionInstance(XdrType[] fields, XdrFieldInfo[] fieldInfos) {
+        switch (fieldInfos[0].getDataType()) {
+            case INTEGER:
+                fields[0] = new XdrInteger((Integer) fieldInfos[0].getValue());
+                break;
+            case UNSIGNED_INTEGER:
+                fields[0] = new XdrUnsignedInteger((Long) fieldInfos[0].getValue());
+                break;
+            case BOOLEAN:
+                fields[0] = new XdrBoolean((Boolean) fieldInfos[0].getValue());
+                break;
+            case ENUM:
+                fields[0] = new FileKindEnumeratedInstance((FileKind) fieldInfos[0].getValue());
+                break;
+            default:
+                throw new RuntimeException("Wrong discriminant type for union: " + fieldInfos[0].getDataType());
+        }
+
+        switch (fieldInfos[1].getDataType()) {
+            case INTEGER:
+                fields[1] = new XdrInteger((Integer) fieldInfos[1].getValue());
+                break;
+            case UNSIGNED_INTEGER:
+                fields[1] = new XdrUnsignedInteger((Long) fieldInfos[1].getValue());
+                break;
+            case BOOLEAN:
+                fields[1] = new XdrBoolean((Boolean) fieldInfos[1].getValue());
+                break;
+            case STRING:
+                fields[1] = new XdrString((String) fieldInfos[1].getValue());
+                break;
+            default:
+                fields[1] = null;
+        }
+    }
+
+    @Override
+    protected XdrUnion fieldsToValues(AbstractXdrType[] fields) {
+        XdrFieldInfo[] fieldInfos = {new XdrFieldInfo(0, XdrDataType.ENUM, fields[0].getValue()),
+                new XdrFieldInfo(1, XdrDataType.STRING,fields[1].getValue())};
+        return new XdrUnionInstance(fieldInfos);
+    }
+
+    @Override
+    protected AbstractXdrType[] getAllFields() {
+        AbstractXdrType[] fields = new AbstractXdrType[2];
+        fields[0] = new FileKindEnumeratedInstance();
+        fields[1] = new XdrString();
+        return fields;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/8188a127/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionTest.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionTest.java b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionTest.java
new file mode 100644
index 0000000..ae8ee6e
--- /dev/null
+++ b/kerby-common/kerby-xdr/src/test/java/org/apache/kerby/xdr/XdrUnionTest.java
@@ -0,0 +1,67 @@
+/**
+ *  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.kerby.xdr;
+
+import org.apache.kerby.xdr.type.XdrUnion;
+import org.apache.kerby.xdr.util.HexUtil;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class XdrUnionTest {
+    @Test
+    public void testEncoding() throws IOException {
+        UnionFileTypeSwitch fileType = new UnionFileTypeSwitch(FileKind.EXEC);
+        testEncodingWith(fileType, "0x00 00 00 02 00 00 00 04 6c 69 73 70");
+    }
+
+    private void testEncodingWith(UnionFileTypeSwitch value, String expectedEncoding) throws IOException {
+        byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
+        XdrFieldInfo[] fieldInfos = {new XdrFieldInfo(0, value.getFileKind(), value.getFileValue()),
+                new XdrFieldInfo(1, value.getArmKind(), value.getArmValue())};
+
+        XdrUnion aValue = new XdrUnionInstance(fieldInfos);
+
+        byte[] encodingBytes = aValue.encode();
+        assertThat(encodingBytes).isEqualTo(expected);
+    }
+
+
+    @Test
+    public void testDecoding() throws IOException {
+        UnionFileTypeSwitch fileType = new UnionFileTypeSwitch(FileKind.EXEC);
+        testEncodingWith(fileType, "0x00 00 00 02 00 00 00 04 6c 69 73 70");
+    }
+
+    private void testDecodingWith(UnionFileTypeSwitch expectedValue, String content) throws IOException {
+        XdrUnion decoded = new XdrUnionInstance();
+
+        decoded.decode(HexUtil.hex2bytesFriendly(content));
+
+        XdrFieldInfo[] fieldInfos = decoded.getValue().getXdrFieldInfos();
+        assertThat(fieldInfos.length).isEqualTo(2);
+        assertThat(fieldInfos[0].getDataType()).isEqualTo(expectedValue.getFileKind());
+        assertThat((FileKind) fieldInfos[0].getValue()).isEqualTo(expectedValue.getFileValue());
+        assertThat(fieldInfos[1].getDataType()).isEqualTo(expectedValue.getArmKind());
+        assertThat((String) fieldInfos[1].getValue()).isEqualTo(expectedValue.getArmValue());
+    }
+}