directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dran...@apache.org
Subject [22/45] directory-kerberos git commit: DIRKRB-149 New layout structure with the new name "Apache Kerby"
Date Thu, 22 Jan 2015 21:48:01 GMT
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BigInteger.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BigInteger.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BigInteger.java
new file mode 100644
index 0000000..f880840
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BigInteger.java
@@ -0,0 +1,48 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class Asn1BigInteger extends Asn1Simple<BigInteger>
+{
+    public Asn1BigInteger() {
+        this(null);
+    }
+
+    public Asn1BigInteger(long value) {
+        this(BigInteger.valueOf(value));
+    }
+
+    public Asn1BigInteger(BigInteger value) {
+        super(UniversalTag.INTEGER, value);
+    }
+
+    protected void toBytes() {
+        setBytes(getValue().toByteArray());
+    }
+
+    protected void toValue() throws IOException {
+        setValue(new BigInteger(getBytes()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
new file mode 100644
index 0000000..1aa0232
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
@@ -0,0 +1,86 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1BitString extends Asn1Simple<byte[]>
+{
+    private int padding;
+
+    public Asn1BitString() {
+        this(null);
+    }
+
+    public Asn1BitString(byte[] value) {
+        this(value, 0);
+    }
+
+    public Asn1BitString(byte[] value, int padding) {
+        super(UniversalTag.BIT_STRING, value);
+        this.padding = padding;
+    }
+
+    public void setPadding(int padding) {
+        this.padding = padding;
+    }
+
+    public int getPadding() {
+        return padding;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return getValue().length + 1;
+    }
+
+    @Override
+    protected void toBytes() {
+        byte[] bytes = new byte[encodingBodyLength()];
+        bytes[0] = (byte)padding;
+        System.arraycopy(getValue(), 0, bytes, 1, bytes.length - 1);
+        setBytes(bytes);
+    }
+
+    @Override
+    protected void toValue() throws IOException {
+        byte[] bytes = getBytes();
+        if (bytes.length < 1) {
+            throw new IOException("Bad stream, zero bytes found for bitstring");
+        }
+        int paddingBits = bytes[0];
+        validatePaddingBits(paddingBits);
+        setPadding(paddingBits);
+
+        byte[] newBytes = new byte[bytes.length - 1];
+        if (bytes.length > 1) {
+            System.arraycopy(bytes, 1, newBytes, 0, bytes.length - 1);
+        }
+        setValue(newBytes);
+    }
+
+    private void validatePaddingBits(int paddingBits) throws IOException {
+        if (paddingBits < 0 || paddingBits > 7) {
+            throw new IOException("Bad padding number: " + paddingBits + ", should be in [0, 7]");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
new file mode 100644
index 0000000..125b9a2
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
@@ -0,0 +1,72 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1BmpString extends Asn1Simple<String>
+{
+    public Asn1BmpString() {
+        super(null);
+    }
+
+    public Asn1BmpString(String value) {
+        super(UniversalTag.BMP_STRING, value);
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return getValue().length() * 2;
+    }
+
+    protected void toBytes(EncodingOption encodingOption) {
+        String strValue = getValue();
+        int len = strValue.length();
+        byte[] bytes = new byte[len * 2];
+        char c;
+        for (int i = 0; i != len; i++) {
+            c = strValue.charAt(i);
+            bytes[2 * i] = (byte)(c >> 8);
+            bytes[2 * i + 1] = (byte)c;
+        }
+        setBytes(bytes);
+    }
+
+    protected void toValue() throws IOException {
+        byte[] bytes = getBytes();
+        char[]  chars = new char[bytes.length / 2];
+        for (int i = 0; i != chars.length; i++) {
+            chars[i] = (char)((bytes[2 * i] << 8) | (bytes[2 * i + 1] & 0xff));
+        }
+        setValue(new String(chars));
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        if (content.hasLeft() % 2 != 0) {
+            throw new IOException("Bad stream, BMP string expecting multiple of 2 bytes");
+        }
+        super.decodeBody(content);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
new file mode 100644
index 0000000..38e0d38
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
@@ -0,0 +1,71 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1Boolean extends Asn1Simple<Boolean>
+{
+    private static final byte[] TRUE_BYTE = new byte[] { (byte)0xff };
+    private static final byte[] FALSE_BYTE = new byte[] { (byte)0x00 };
+
+    public static final Asn1Boolean TRUE = new Asn1Boolean(true);
+    public static final Asn1Boolean FALSE = new Asn1Boolean(false);
+
+    public Asn1Boolean() {
+        this(null);
+    }
+
+    public Asn1Boolean(Boolean value) {
+        super(UniversalTag.BOOLEAN, value);
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 1;
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        if (content.hasLeft() != 1) {
+            throw new IOException("More than 1 byte found for Boolean");
+        }
+        super.decodeBody(content);
+    }
+
+    @Override
+    protected void toBytes() {
+        setBytes(getValue() ? TRUE_BYTE : FALSE_BYTE);
+    }
+
+    protected void toValue() throws IOException {
+        byte[] bytes = getBytes();
+        if (bytes[0] == 0) {
+            setValue(false);
+        } else if (bytes[0] == 0xff) {
+            setValue(true);
+        } else {
+            setValue(true);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
new file mode 100644
index 0000000..59d4ba5
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
@@ -0,0 +1,173 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.*;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Asn1Choice extends AbstractAsn1Type<Asn1Type> {
+
+    private Asn1FieldInfo[] fieldInfos;
+    private Asn1Type[] fields;
+
+    public Asn1Choice(Asn1FieldInfo[] fieldInfos) {
+        super(TagClass.UNIVERSAL, UniversalTag.CHOICE.getValue());
+        setValue(this);
+        this.fieldInfos = fieldInfos;
+        this.fields = new Asn1Type[fieldInfos.length];
+        setEncodingOption(EncodingOption.CONSTRUCTED);
+    }
+
+    @Override
+    public boolean isConstructed() {
+        return true;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        AbstractAsn1Type field;
+        TaggingOption taggingOption;
+        for (int i = 0; i < fields.length; ++i) {
+            field = (AbstractAsn1Type) fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    taggingOption = fieldInfos[i].getTaggingOption();
+                    return field.taggedEncodingLength(taggingOption);
+                } else {
+                    return field.encodingLength();
+                }
+            }
+        }
+        return 0;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) {
+        Asn1Type field;
+        TaggingOption taggingOption;
+        for (int i = 0; i < fields.length; ++i) {
+            field = fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    taggingOption = fieldInfos[i].getTaggingOption();
+                    field.taggedEncode(buffer, taggingOption);
+                } else {
+                    field.encode(buffer);
+                }
+                break;
+            }
+        }
+    }
+
+    @Override
+    protected void decode(LimitedByteBuffer content) throws IOException {
+        int foundPos = -1;
+        Asn1Item item = decodeOne(content);
+        for (int i = 0; i < fieldInfos.length; ++i) {
+            if (item.isContextSpecific()) {
+                if (fieldInfos[i].getTagNo() == item.tagNo()) {
+                    foundPos = i;
+                    break;
+                }
+            } else {
+                initField(i);
+                if (fields[i].tagFlags() == item.tagFlags() &&
+                        fields[i].tagNo() == item.tagNo()) {
+                    foundPos = i;
+                    break;
+                } else {
+                    fields[i] = null;
+                }
+            }
+        }
+        if (foundPos == -1) {
+            throw new RuntimeException("Unexpected item with (tagFlags, tagNo): ("
+                    + item.tagFlags() + ", " + item.tagNo() + ")");
+        }
+
+        if (! item.isFullyDecoded()) {
+            AbstractAsn1Type fieldValue = (AbstractAsn1Type) fields[foundPos];
+            if (item.isContextSpecific()) {
+                item.decodeValueWith(fieldValue, fieldInfos[foundPos].getTaggingOption());
+            } else {
+                item.decodeValueWith(fieldValue);
+            }
+        }
+        fields[foundPos] = item.getValue();
+    }
+
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        // Not used
+    }
+
+    private void initField(int idx) {
+        try {
+            fields[idx] = fieldInfos[idx].getType().newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Bad field info specified at index of " + idx, e);
+        }
+    }
+
+    protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
+        Asn1Type value = fields[index];
+        if (value == null) return null;
+        return (T) value;
+    }
+
+    protected void setFieldAs(int index, Asn1Type value) {
+        fields[index] = value;
+    }
+
+    protected String getFieldAsString(int index) {
+        Asn1Type value = fields[index];
+        if (value == null) return null;
+
+        if (value instanceof Asn1String) {
+            return ((Asn1String) value).getValue();
+        }
+
+        throw new RuntimeException("The targeted field type isn't of string");
+    }
+
+    protected byte[] getFieldAsOctets(int index) {
+        Asn1OctetString value = getFieldAs(index, Asn1OctetString.class);
+        if (value != null) return value.getValue();
+        return null;
+    }
+
+    protected void setFieldAsOctets(int index, byte[] bytes) {
+        Asn1OctetString value = new Asn1OctetString(bytes);
+        setFieldAs(index, value);
+    }
+
+    protected Integer getFieldAsInteger(int index) {
+        Asn1Integer value = getFieldAs(index, Asn1Integer.class);
+        if (value != null) {
+            return value.getValue();
+        }
+        return null;
+    }
+
+    protected void setFieldAsInt(int index, int value) {
+        setFieldAs(index, new Asn1Integer(value));
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
new file mode 100644
index 0000000..58dc6a3
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
@@ -0,0 +1,137 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Asn1Collection extends AbstractAsn1Type<List<Asn1Item>>
+{
+    public Asn1Collection(TagClass tagClass, int tagNo) {
+        super(tagClass, tagNo);
+        setValue(new ArrayList<Asn1Item>());
+        setEncodingOption(EncodingOption.CONSTRUCTED);
+    }
+
+    @Override
+    public boolean isConstructed() {
+        return true;
+    }
+
+    public void addItem(Asn1Type value) {
+        if (value instanceof Asn1Item) {
+            getValue().add((Asn1Item) value);
+        } else {
+            getValue().add(new Asn1Item(value));
+        }
+    }
+
+    public void clear() {
+        getValue().clear();
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        List<Asn1Item> valueItems = getValue();
+        int allLen = 0;
+        for (Asn1Item item : valueItems) {
+            if (item != null) {
+                allLen += item.encodingLength();
+            }
+        }
+        return allLen;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) {
+        List<Asn1Item> valueItems = getValue();
+        for (Asn1Item item : valueItems) {
+            if (item != null) {
+                item.encode(buffer);
+            }
+        }
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        while (content.available()) {
+            Asn1Type aValue = decodeOne(content);
+            if (aValue != null) {
+                if (aValue instanceof Asn1Item) {
+                    addItem((Asn1Item) aValue);
+                } else {
+                    addItem(aValue);
+                }
+            } else {
+                throw new RuntimeException("Unexpected running into here");
+            }
+        }
+    }
+
+    public static boolean isCollection(int tagNo) {
+        return isCollection(UniversalTag.fromValue(tagNo));
+    }
+
+    public static boolean isCollection(UniversalTag tagNo) {
+        switch (tagNo) {
+            case SEQUENCE:
+            case SEQUENCE_OF:
+            case SET:
+            case SET_OF:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static Asn1Type createCollection(int tagNo) {
+        if (! isCollection(tagNo)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + tagNo);
+        }
+        return createCollection(UniversalTag.fromValue(tagNo));
+    }
+
+    public static Asn1Type createCollection(UniversalTag tagNo) {
+        if (! isCollection(tagNo)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + tagNo);
+        }
+
+        switch (tagNo) {
+            case SEQUENCE:
+                return new Asn1Sequence();
+            case SEQUENCE_OF:
+                return new Asn1Sequence();
+            case SET:
+                return new Asn1Set();
+            case SET_OF:
+                return new Asn1Set();
+            default:
+                throw new IllegalArgumentException("Unexpected tag " + tagNo.getValue());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
new file mode 100644
index 0000000..5a8709f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
@@ -0,0 +1,88 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TagClass;
+
+import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class Asn1CollectionOf<T extends Asn1Type> extends Asn1Collection
+{
+    public Asn1CollectionOf(TagClass tagClass, int tagNo) {
+        super(tagClass, tagNo);
+    }
+
+    public List<T> getElements() {
+        List<Asn1Item> items = getValue();
+        int nElements = items != null ? items.size() : 0;
+        List<T> results = new ArrayList<T>(nElements);
+        if (nElements > 0) {
+            for (Asn1Item item : items) {
+                if (!item.isFullyDecoded()) {
+                    try {
+                        item.decodeValueAs(getElementType());
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                results.add((T) item.getValue());
+            }
+        }
+        return results;
+    }
+
+    public void setElements(List<T> elements) {
+        super.clear();
+
+        for (T ele : elements) {
+            addElement(ele);
+        }
+    }
+
+    public void addElements(T ... elements) {
+        for (T ele : elements) {
+            addElement(ele);
+        }
+    }
+
+    public void addElement(T element) {
+        super.addItem(element);
+    }
+
+    @Override
+    public void addItem(Asn1Type value) {
+        Class<T> eleType = getElementType();
+        if (value instanceof Asn1Item) {
+            super.addItem(value);
+        } else if (! eleType.isInstance(value)) {
+            throw new RuntimeException("Unexpected element type " + value.getClass().getCanonicalName());
+        } else {
+            addElement((T) value);
+        }
+    }
+
+    protected Class<T> getElementType() {
+        Class<T> elementType = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+        return elementType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
new file mode 100644
index 0000000..b506c2f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
@@ -0,0 +1,195 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.TaggingOption;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * For collection type that may consist of tagged fields
+ */
+public abstract class Asn1CollectionType extends AbstractAsn1Type<Asn1CollectionType> {
+    private Asn1FieldInfo[] fieldInfos;
+    private Asn1Type[] fields;
+
+    public Asn1CollectionType(int universalTagNo, Asn1FieldInfo[] fieldInfos) {
+        super(TagClass.UNIVERSAL, universalTagNo);
+        setValue(this);
+        this.fieldInfos = fieldInfos;
+        this.fields = new Asn1Type[fieldInfos.length];
+        setEncodingOption(EncodingOption.CONSTRUCTED);
+    }
+
+    @Override
+    public boolean isConstructed() {
+        return true;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        int allLen = 0;
+        AbstractAsn1Type field;
+        TaggingOption taggingOption;
+        for (int i = 0; i < fields.length; ++i) {
+            field = (AbstractAsn1Type) fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    taggingOption = fieldInfos[i].getTaggingOption();
+                    allLen += field.taggedEncodingLength(taggingOption);
+                } else {
+                    allLen += field.encodingLength();
+                }
+            }
+        }
+        return allLen;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) {
+        Asn1Type field;
+        TaggingOption taggingOption;
+        for (int i = 0; i < fields.length; ++i) {
+            field = fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    taggingOption = fieldInfos[i].getTaggingOption();
+                    field.taggedEncode(buffer, taggingOption);
+                } else {
+                    field.encode(buffer);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        initFields();
+
+        Asn1Collection coll = createCollection();
+        coll.decode(tagFlags(), tagNo(), content);
+
+        int lastPos = -1, foundPos = -1;
+        for (Asn1Item item : coll.getValue()) {
+            foundPos = -1;
+            for (int i = lastPos + 1; i < fieldInfos.length; ++i) {
+                if (item.isContextSpecific()) {
+                    if(fieldInfos[i].getTagNo() == item.tagNo()) {
+                        foundPos = i;
+                        break;
+                    }
+                } else if (fields[i].tagFlags() == item.tagFlags() &&
+                        fields[i].tagNo() == item.tagNo()) {
+                    foundPos = i;
+                    break;
+                }
+            }
+            if (foundPos == -1) {
+                throw new RuntimeException("Unexpected item with (tagFlags, tagNo): ("
+                        + item.tagFlags() + ", " + item.tagNo() + ")");
+            }
+
+            if (! item.isFullyDecoded()) {
+                AbstractAsn1Type fieldValue = (AbstractAsn1Type) fields[foundPos];
+                if (item.isContextSpecific()) {
+                    item.decodeValueWith(fieldValue, fieldInfos[foundPos].getTaggingOption());
+                } else {
+                    item.decodeValueWith(fieldValue);
+                }
+            }
+            fields[foundPos] = item.getValue();
+            lastPos = foundPos;
+        }
+    }
+
+    private void initFields() {
+        for (int i = 0; i < fieldInfos.length; ++i) {
+            try {
+                fields[i] = fieldInfos[i].getType().newInstance();
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Bad field info specified at index of " + i, e);
+            }
+        }
+    }
+
+    protected abstract Asn1Collection createCollection();
+
+    protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
+        Asn1Type value = fields[index];
+        if (value == null) return null;
+        return (T) value;
+    }
+
+    protected void setFieldAs(int index, Asn1Type value) {
+        fields[index] = value;
+    }
+
+    protected String getFieldAsString(int index) {
+        Asn1Type value = fields[index];
+        if (value == null) return null;
+
+        if (value instanceof Asn1String) {
+            return ((Asn1String) value).getValue();
+        }
+
+        throw new RuntimeException("The targeted field type isn't of string");
+    }
+
+    protected byte[] getFieldAsOctets(int index) {
+        Asn1OctetString value = getFieldAs(index, Asn1OctetString.class);
+        if (value != null) return value.getValue();
+        return null;
+    }
+
+    protected void setFieldAsOctets(int index, byte[] bytes) {
+        Asn1OctetString value = new Asn1OctetString(bytes);
+        setFieldAs(index, value);
+    }
+
+    protected Integer getFieldAsInteger(int index) {
+        Asn1Integer value = getFieldAs(index, Asn1Integer.class);
+        if (value != null) {
+            return value.getValue();
+        }
+        return null;
+    }
+
+    protected void setFieldAsInt(int index, int value) {
+        setFieldAs(index, new Asn1Integer(value));
+    }
+
+    protected Asn1Type getFieldAsAny(int index) {
+        Asn1Any any = getFieldAs(index, Asn1Any.class);
+        if (any != null) {
+            return any.getValue();
+        }
+        return null;
+    }
+
+    protected void setFieldAsAny(int index, Asn1Type value) {
+        if (value != null) {
+            setFieldAs(index, new Asn1Any(value));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
new file mode 100644
index 0000000..0647159
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
@@ -0,0 +1,76 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TaggingOption;
+
+public class Asn1FieldInfo {
+    private int index;
+    private int tagNo;
+    private boolean isImplicit;
+    private Class<? extends Asn1Type> type;
+
+    public Asn1FieldInfo(int index, int tagNo, Class<? extends Asn1Type> type) {
+        this(index, tagNo, type, false);
+    }
+
+    public Asn1FieldInfo(int index, Class<? extends Asn1Type> type) {
+        this(index, index, type, false);
+    }
+
+    public Asn1FieldInfo(int index, Class<? extends Asn1Type> type, boolean isImplicit) {
+        this(index, index, type, isImplicit);
+    }
+
+    public Asn1FieldInfo(int index, int tagNo, Class<? extends Asn1Type> type, boolean isImplicit) {
+        this.index = index;
+        this.tagNo = tagNo;
+        this.type = type;
+        this.isImplicit = isImplicit;
+    }
+
+    public boolean isTagged() {
+        return tagNo != -1;
+    }
+
+    public TaggingOption getTaggingOption() {
+        if (isImplicit) {
+            return TaggingOption.newImplicitContextSpecific(tagNo);
+        } else {
+            return TaggingOption.newExplicitContextSpecific(tagNo);
+        }
+    }
+
+    public int getTagNo() {
+        return tagNo;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isImplicit() {
+        return isImplicit;
+    }
+
+    public Class<? extends Asn1Type> getType() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
new file mode 100644
index 0000000..19c6d40
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
@@ -0,0 +1,33 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1GeneralString extends Asn1String
+{
+    public Asn1GeneralString() {
+        super(UniversalTag.GENERAL_STRING);
+    }
+
+    public Asn1GeneralString(String value) {
+        super(UniversalTag.GENERAL_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
new file mode 100644
index 0000000..9341f1a
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
@@ -0,0 +1,134 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+public class Asn1GeneralizedTime extends Asn1Simple<Date>
+{
+    public Asn1GeneralizedTime() {
+        this(null);
+    }
+
+    /**
+     * time in milliseconds
+     */
+    public Asn1GeneralizedTime(long time) {
+        super(UniversalTag.GENERALIZED_TIME, new Date(time));
+    }
+
+    public Asn1GeneralizedTime(Date date) {
+        super(UniversalTag.UTC_TIME, date);
+    }
+
+    protected void toValue() throws IOException {
+        String dateStr = new String(getBytes(), StandardCharsets.US_ASCII);
+        SimpleDateFormat sdf;
+        String fixedDateStr = dateStr;
+
+        boolean withZ = dateStr.endsWith("Z");
+        String timeZonePart = getTimeZonePart(dateStr);
+        boolean withZone = timeZonePart != null;
+        String millSecs = getMillSeconds(dateStr);
+
+        fixedDateStr = dateStr.substring(0, 14) + millSecs;
+        if (withZ) {
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else if (withZone) {
+            fixedDateStr += timeZonePart;
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSSz");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else {
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+        }
+
+        try {
+            setValue(sdf.parse(fixedDateStr));
+        } catch (ParseException e) {
+            throw new IOException("Failed to parse as generalized time string " + dateStr);
+        }
+    }
+
+    @Override
+    protected void toBytes() {
+        Date date = getValue();
+        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+        String str = dateF.format(date);
+        byte[] bytes = str.getBytes(StandardCharsets.US_ASCII);
+        setBytes(bytes);
+    }
+
+    /**
+     * Extract the fractional part in seconds and convert into integer by (frac * 1000) as milli seconds
+     */
+    private String getMillSeconds(String dateStr) {
+        char[] millDigits = new char[] {'0', '0', '0'};
+
+        int iPos = dateStr.indexOf('.');
+        if (iPos > 0) {
+            if (iPos != 14) {
+                throw new IllegalArgumentException("Bad generalized time string, " +
+                        "with improper milli seconds " + dateStr);
+            }
+
+            char chr;
+            int j = 0;
+            for (int i = 15; i < dateStr.length() && j < millDigits.length; i++) {
+                chr = dateStr.charAt(i);
+                if ('0' <= chr && chr <= '9') {
+                    millDigits[j++] = chr;
+                } else break;
+            }
+        }
+
+        return new String(millDigits);
+    }
+
+    /**
+     * Extract the timezone part if any
+     */
+    private String getTimeZonePart(String dateStr) {
+        int iPos = dateStr.indexOf('+');
+        if (iPos == -1) {
+            iPos = dateStr.indexOf('-');
+        }
+        if (iPos > 0 && iPos != dateStr.length() - 5) {
+            throw new IllegalArgumentException("Bad generalized time string, " +
+                    "with improper timezone part " + dateStr);
+        }
+
+        if (iPos > 0) {
+            return dateStr.substring(iPos);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
new file mode 100644
index 0000000..6f73c9f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
@@ -0,0 +1,33 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1IA5String extends Asn1String
+{
+    public Asn1IA5String() {
+        super(UniversalTag.IA5_STRING);
+    }
+
+    public Asn1IA5String(String value) {
+        super(UniversalTag.IA5_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
new file mode 100644
index 0000000..b0893a0
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
@@ -0,0 +1,46 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class Asn1Integer extends Asn1Simple<Integer>
+{
+    public Asn1Integer() {
+        this(null);
+    }
+
+    public Asn1Integer(Integer value) {
+        super(UniversalTag.INTEGER, value);
+    }
+
+    @Override
+    protected void toBytes() {
+        setBytes(BigInteger.valueOf(getValue()).toByteArray());
+    }
+
+    @Override
+    protected void toValue() throws IOException {
+        setValue(new BigInteger(getBytes()).intValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
new file mode 100644
index 0000000..a18d135
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
@@ -0,0 +1,155 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.Asn1Factory;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TaggingOption;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Asn1Item serves two purposes:
+ * 1. Wrapping an existing Asn1Type value for Asn1Collection;
+ * 2. Wrapping a half decoded value whose body content is left to be decoded later when appropriate.
+ * Why not fully decoded at once? Lazy and decode on demand for collection, or impossible due to lacking
+ * key parameters, like implicit encoded value for tagged value.
+ *
+ * For not fully decoded value, you tell your case using isSimple/isCollection/isTagged/isContextSpecific etc.,
+ * then call decodeValueAsSimple/decodeValueAsCollection/decodeValueAsImplicitTagged/decodeValueAsExplicitTagged etc.
+ * to decode it fully. Or if you have already derived the value holder or the holder type, you can use decodeValueWith
+ * or decodeValueAs with your holder or hodler type.
+ */
+public class Asn1Item extends AbstractAsn1Type<Asn1Type>
+{
+    private LimitedByteBuffer bodyContent;
+
+    public Asn1Item(Asn1Type value) {
+        super(value.tagFlags(), value.tagNo(), value);
+    }
+
+    public Asn1Item(int tag, int tagNo, LimitedByteBuffer bodyContent) {
+        super(tag, tagNo);
+        this.bodyContent = bodyContent;
+    }
+
+    public LimitedByteBuffer getBodyContent() {
+        return bodyContent;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        if (getValue() != null) {
+            return ((AbstractAsn1Type) getValue()).encodingBodyLength();
+        }
+        return (int) bodyContent.hasLeft();
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) {
+        if (getValue() != null) {
+            ((AbstractAsn1Type) getValue()).encodeBody(buffer);
+        } else {
+            try {
+                buffer.put(bodyContent.readAllLeftBytes());
+            } catch (IOException e) {
+                throw new RuntimeException("Failed to read all left bytes from body content", e);
+            }
+        }
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer bodyContent) throws IOException {
+        this.bodyContent = bodyContent;
+    }
+
+    public boolean isFullyDecoded() {
+        return getValue() != null;
+    }
+
+    public void decodeValueAsSimple() throws IOException {
+        if (getValue() != null) return;
+        if (! isSimple()) {
+            throw new IllegalArgumentException("Attempting to decode non-simple value as simple");
+        }
+
+        Asn1Type value = Asn1Factory.create(tagNo());
+        decodeValueWith(value);
+    }
+
+    public void decodeValueAsCollection() throws IOException {
+        if (getValue() != null) return;
+        if (! isCollection()) {
+            throw new IllegalArgumentException("Attempting to decode non-collection value as collection");
+        }
+
+        Asn1Type value = Asn1Factory.create(tagNo());
+        decodeValueWith(value);
+    }
+
+    public void decodeValueAs(Class<? extends Asn1Type> type) throws IOException {
+        Asn1Type value;
+        try {
+            value = type.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException("Invalid type: " + type.getCanonicalName(), e);
+        }
+        decodeValueWith(value);
+    }
+
+    public void decodeValueWith(Asn1Type value) throws IOException {
+        setValue(value);
+        ((AbstractAsn1Type) value).decode(tagFlags(), tagNo(), bodyContent);
+    }
+
+    public void decodeValueAsImplicitTagged(int originalTag, int originalTagNo) throws IOException {
+        if (! isTagged()) {
+            throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+        }
+        Asn1Item taggedValue = new Asn1Item(originalTag, originalTagNo, getBodyContent());
+        decodeValueWith(taggedValue);
+    }
+
+    public void decodeValueAsExplicitTagged() throws IOException {
+        if (! isTagged()) {
+            throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+        }
+        Asn1Item taggedValue = decodeOne(getBodyContent());
+        decodeValueWith(taggedValue);
+    }
+
+    private void decodeValueWith(Asn1Item taggedValue) throws IOException {
+        taggedValue.decodeValueAsSimple();
+        if (taggedValue.isFullyDecoded()) {
+            setValue(taggedValue.getValue());
+        } else {
+            setValue(taggedValue);
+        }
+    }
+
+    public void decodeValueWith(Asn1Type value, TaggingOption taggingOption) throws IOException {
+        if (! isTagged()) {
+            throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+        }
+        ((AbstractAsn1Type) value).taggedDecode(tagFlags(), tagNo(), getBodyContent(), taggingOption);
+        setValue(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
new file mode 100644
index 0000000..8cabc04
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.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.kerby.asn1.type;
+
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1Null extends Asn1Simple<Object>
+{
+    public static final Asn1Null NULL = new Asn1Null();
+    private static final byte[]  EMPTY_BYTES = new byte[0];
+
+    public Asn1Null() {
+        super(null, UniversalTag.NULL);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return EMPTY_BYTES;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 0;
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        if (content.hasLeft() != 0) {
+            throw new IOException("Unexpected bytes found for NULL");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
new file mode 100644
index 0000000..ea534ac
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
@@ -0,0 +1,50 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1NumericsString extends Asn1String
+{
+    public Asn1NumericsString() {
+        this(null);
+    }
+
+    public Asn1NumericsString(String value) {
+        super(UniversalTag.NUMERIC_STRING, value);
+        if (value != null) {
+            if (!isNumeric(value)) {
+                throw new IllegalArgumentException("Invalid numeric string");
+            }
+        }
+    }
+
+    public static boolean isNumeric(String  s) {
+        char c;
+        for (int i = s.length() - 1; i >= 0; i--) {
+            c = s.charAt(i);
+            if ((c >= '0' && c <= '9') || c == ' ') {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
new file mode 100644
index 0000000..e6a49ec
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
@@ -0,0 +1,164 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+public class Asn1ObjectIdentifier extends Asn1Simple<String>
+{
+    public Asn1ObjectIdentifier() {
+        this(null);
+    }
+
+    public Asn1ObjectIdentifier(String value) {
+        super(UniversalTag.OBJECT_IDENTIFIER, value);
+    }
+
+    @Override
+    protected void toBytes() {
+        byte[][] bytesArr = convert(getValue());
+        int allLen = 0;
+        for (byte[] bytes : bytesArr) {
+            allLen += bytes.length;
+        }
+        ByteBuffer buffer = ByteBuffer.allocate(allLen);
+        for (byte[] bytes : bytesArr) {
+            buffer.put(bytes);
+        }
+        setBytes(buffer.array());
+    }
+
+    protected void toValue() {
+        StringBuilder sb = new StringBuilder();
+
+        byte[] bytes = getBytes();
+        byte[][] bytesGroups = group(bytes);
+        BigInteger[] coms = convert(bytesGroups);
+
+        long first = coms[0].longValue();
+        sb.append(first / 40).append('.');
+        sb.append(first % 40);
+        if (coms.length > 1) {
+            sb.append('.');
+        }
+
+        for (int i = 1; i < coms.length; ++i) {
+            sb.append(coms[i].toString());
+            if (i != coms.length - 1) {
+                sb.append('.');
+            }
+        }
+
+        String value = sb.toString();
+        setValue(value);
+    }
+
+    private BigInteger[] convert(byte[][] bytesGroups) {
+        BigInteger[] comps = new BigInteger[bytesGroups.length];
+
+        for (int i = 0; i < bytesGroups.length; ++i) {
+            comps[i] = convert(bytesGroups[i]);
+        }
+
+        return comps;
+    }
+
+    private BigInteger convert(byte[] bytes) {
+        BigInteger value = BigInteger.valueOf(bytes[0] & 0x7f);
+        for (int i = 1; i < bytes.length; ++i) {
+            value = value.shiftLeft(7);
+            value = value.or(BigInteger.valueOf(bytes[i] & 0x7f));
+        }
+
+        return value;
+    }
+
+    /**
+     * divide and group bytes together belonging to each component
+     */
+    private byte[][] group(byte[] bytes) {
+        int count = 0, i, j;
+        int[] countArr = new int[bytes.length]; // how many bytes for each group
+        for (i = 0; i < countArr.length; ++i) countArr[i] = 0;
+
+        for (j = 0, i = 0; i < bytes.length; ++i) {
+            if ((bytes[i] & 0x80) != 0) {
+                countArr[j]++;
+            } else {
+                countArr[j++]++;
+            }
+        }
+        count = j;
+
+        byte[][] bytesGroups = new byte[count][];
+        for (i = 0; i < count; ++i) {
+            bytesGroups[i] = new byte[countArr[i]];
+        }
+
+        int k = 0;
+        for (j = 0, i = 0; i < bytes.length; ++i) {
+            bytesGroups[j][k++] = bytes[i];
+            if ((bytes[i] & 0x80) == 0) {
+                j++;
+                k = 0;
+            }
+        }
+
+        return bytesGroups;
+    }
+
+    private byte[][] convert(String oid) {
+        String[] parts = oid.split("\\.");
+        BigInteger[] coms = new BigInteger[parts.length - 1];
+        for (int i = 1; i < parts.length; ++i) {
+            coms[i - 1] = new BigInteger(parts[i]);
+        }
+        coms[0] = coms[0].add(BigInteger.valueOf(Integer.parseInt(parts[0]) * 40));
+
+        byte[][] bytesGroups = new byte[coms.length][];
+        for (int i = 0; i < coms.length; ++i) {
+            bytesGroups[i] = convert(coms[i]);
+        }
+
+        return bytesGroups;
+    }
+
+    private byte[] convert(BigInteger value) {
+        int bitLen = value.bitLength();
+
+        if (bitLen < 8) {
+            return new byte[] { value.byteValue() };
+        }
+
+        int len = (bitLen + 6) / 7;
+        byte[] bytes = new byte[len];
+        BigInteger tmpValue = value;
+        for (int i = len - 1; i >= 0; i--) {
+            bytes[i] = (byte)((tmpValue.byteValue() & 0x7f) | 0x80);
+            tmpValue = tmpValue.shiftRight(7);
+        }
+        bytes[len - 1] &= 0x7f;
+
+        return bytes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
new file mode 100644
index 0000000..72510a3
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
@@ -0,0 +1,51 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1OctetString extends Asn1Simple<byte[]>
+{
+    public Asn1OctetString() {
+        this(null);
+    }
+
+    public Asn1OctetString(byte[] value) {
+        super(UniversalTag.OCTET_STRING, value);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return getValue();
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return getValue().length;
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        setValue(content.readAllLeftBytes());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
new file mode 100644
index 0000000..78fdb10
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
@@ -0,0 +1,33 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1PrintableString extends Asn1String
+{
+    public Asn1PrintableString() {
+        this(null);
+    }
+
+    public Asn1PrintableString(String value) {
+        super(UniversalTag.PRINTABLE_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
new file mode 100644
index 0000000..b9e374c
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
@@ -0,0 +1,30 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1Sequence extends Asn1Collection
+{
+    public Asn1Sequence() {
+        super(TagClass.UNIVERSAL, UniversalTag.SEQUENCE.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
new file mode 100644
index 0000000..dcf6356
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
@@ -0,0 +1,38 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1SequenceOf<T extends Asn1Type> extends Asn1CollectionOf<T>
+{
+    public Asn1SequenceOf() {
+        super(TagClass.UNIVERSAL, UniversalTag.SEQUENCE_OF.getValue());
+    }
+
+    public boolean isEmpty() {
+        return (getValue() == null || getElements().size() == 0);
+    }
+
+    public void add(T element) {
+        getElements().add(element);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
new file mode 100644
index 0000000..bcbf715
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
@@ -0,0 +1,37 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+/**
+ * For sequence type that consists of tagged fields
+ */
+public class Asn1SequenceType extends Asn1CollectionType {
+
+    public Asn1SequenceType(Asn1FieldInfo[] tags) {
+        super(UniversalTag.SEQUENCE.getValue(), tags);
+    }
+
+    @Override
+    protected Asn1Collection createCollection() {
+        return new Asn1Sequence();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
new file mode 100644
index 0000000..3407e8c
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
@@ -0,0 +1,30 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1Set extends Asn1Collection
+{
+    public Asn1Set() {
+        super(TagClass.UNIVERSAL, UniversalTag.SET.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
new file mode 100644
index 0000000..f91e241
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
@@ -0,0 +1,30 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1SetOf<T extends Asn1Type> extends Asn1CollectionOf<T>
+{
+    public Asn1SetOf() {
+        super(TagClass.UNIVERSAL, UniversalTag.SET_OF.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
new file mode 100644
index 0000000..4f13369
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
@@ -0,0 +1,37 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+/**
+ * For set type that consists of tagged fields
+ */
+public class Asn1SetType extends Asn1CollectionType {
+
+    public Asn1SetType(Asn1FieldInfo[] tags) {
+        super(UniversalTag.SET.getValue(), tags);
+    }
+
+    @Override
+    protected Asn1Collection createCollection() {
+        return new Asn1Set();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/ceacb982/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
new file mode 100644
index 0000000..c25309d
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
@@ -0,0 +1,184 @@
+/**
+ *  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.asn1.type;
+
+import org.apache.kerby.asn1.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public abstract class Asn1Simple<T> extends AbstractAsn1Type<T> {
+    private byte[] bytes;
+
+    public Asn1Simple(UniversalTag tagNo) {
+        this(tagNo, null);
+    }
+
+    public Asn1Simple(UniversalTag tagNo, T value) {
+        super(TagClass.UNIVERSAL, tagNo.getValue(), value);
+        setEncodingOption(EncodingOption.PRIMITIVE);
+    }
+
+    protected byte[] getBytes() {
+        return bytes;
+    }
+
+    protected void setBytes(byte[] bytes) {
+        this.bytes = bytes;
+    }
+
+    @Override
+    public void encode(ByteBuffer buffer) {
+        encodeTag(buffer, tagFlags(), tagNo());
+        int bodyLen = encodingBodyLength();
+        encodeLength(buffer, bodyLen);
+        if (bodyLen > 0) {
+            buffer.put(encodeBody());
+        }
+    }
+
+    protected byte[] encodeBody() {
+        if (bytes == null) {
+            toBytes();
+        }
+        return bytes;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) {
+        buffer.put(encodeBody());
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        if (getValue() == null) {
+            return 0;
+        }
+        if (bytes == null) {
+            toBytes();
+        }
+        return bytes.length;
+    }
+
+    @Override
+    protected void decodeBody(LimitedByteBuffer content) throws IOException {
+        byte[] leftBytes = content.readAllLeftBytes();
+        if (leftBytes.length > 0) {
+            setBytes(leftBytes);
+            toValue();
+        }
+    }
+
+    @Override
+    public boolean isConstructed() {
+        return false;
+    }
+
+    protected void toValue() throws IOException {}
+
+    protected void toBytes() {}
+
+    public static boolean isSimple(int tagNo) {
+        return isSimple(UniversalTag.fromValue(tagNo));
+    }
+
+    public static boolean isSimple(UniversalTag tagNo) {
+        switch (tagNo) {
+            case BIT_STRING:
+            case BMP_STRING:
+            case BOOLEAN:
+            case ENUMERATED:
+            case GENERALIZED_TIME:
+            case GENERAL_STRING:
+            case IA5_STRING:
+            case INTEGER:
+            case NULL:
+            case NUMERIC_STRING:
+            case OBJECT_IDENTIFIER:
+            case OCTET_STRING:
+            case PRINTABLE_STRING:
+            case T61_STRING:
+            case UNIVERSAL_STRING:
+            case UTC_TIME:
+            case UTF8_STRING:
+            case VISIBLE_STRING:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static Asn1Type createSimple(int tagNo) {
+        if (! isSimple(tagNo)) {
+            throw new IllegalArgumentException("Not simple type, tag: " + tagNo);
+        }
+        return createSimple(UniversalTag.fromValue(tagNo));
+    }
+
+    public static Asn1Type createSimple(UniversalTag tagNo) {
+        if (! isSimple(tagNo)) {
+            throw new IllegalArgumentException("Not simple type, tag: " + tagNo);
+        }
+
+        switch (tagNo) {
+            case BIT_STRING:
+                return new Asn1BitString();
+            case BMP_STRING:
+                return new Asn1BmpString();
+            case BOOLEAN:
+                return new Asn1Boolean();
+            case ENUMERATED:
+                return null;
+            case GENERALIZED_TIME:
+                return new Asn1GeneralizedTime();
+            case GENERAL_STRING:
+                return new Asn1GeneralString();
+            case IA5_STRING:
+                return new Asn1IA5String();
+            case INTEGER:
+                return new Asn1Integer();
+            case NULL:
+                return new Asn1Null();
+            case NUMERIC_STRING:
+                return new Asn1NumericsString();
+            case OBJECT_IDENTIFIER:
+                return new Asn1ObjectIdentifier();
+            case OCTET_STRING:
+                return new Asn1OctetString();
+            case PRINTABLE_STRING:
+                return new Asn1PrintableString();
+            case T61_STRING:
+                return new Asn1T61String();
+            case UNIVERSAL_STRING:
+                return new Asn1UniversalString();
+            case UTC_TIME:
+                return new Asn1UtcTime();
+            case UTF8_STRING:
+                return new Asn1Utf8String();
+            case VISIBLE_STRING:
+                return new Asn1VisibleString();
+            default:
+                throw new IllegalArgumentException("Unexpected tag " + tagNo.getValue());
+        }
+    }
+}


Mime
View raw message