You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2016/01/16 10:49:28 UTC
[30/36] directory-kerby git commit: Consolidated facility and support
modules into kerby-common
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
new file mode 100644
index 0000000..08a9019
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
@@ -0,0 +1,188 @@
+/**
+ * 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;
+
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+import org.apache.kerby.asn1.parse.Asn1Parser;
+import org.apache.kerby.asn1.type.Asn1Type;
+import org.apache.kerby.asn1.util.HexUtil;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The shortcut API for ASN1 encoding, decoding and dumping.
+ */
+public final class Asn1 {
+
+ private Asn1() {
+
+ }
+
+ /**
+ * Encode value into buffer.
+ * @param buffer
+ * @param value
+ * @throws IOException
+ */
+ public static void encode(ByteBuffer buffer, Asn1Type value) throws IOException {
+ value.encode(buffer);
+ }
+
+ /**
+ * Encode value and return the result.
+ * @param value
+ * @return
+ * @throws IOException
+ */
+ public static byte[] encode(Asn1Type value) throws IOException {
+ return value.encode();
+ }
+
+ /**
+ * Blindly decode content and return the result ASN1 object.
+ * @param content
+ * @return
+ * @throws IOException
+ */
+ public static Asn1Type decode(byte[] content) throws IOException {
+ return decode(ByteBuffer.wrap(content));
+ }
+
+ /**
+ * See avove.
+ */
+ public static Asn1Type decode(ByteBuffer content) throws IOException {
+ Asn1ParseResult parseResult = Asn1Parser.parse(content);
+ return Asn1Converter.convert(parseResult, false);
+ }
+
+ /**
+ * Decode using specified value container. Better to use this when the value
+ * type is known prior to the call.
+ * @param content
+ * @param value
+ * @throws IOException
+ */
+ public static void decode(byte[] content, Asn1Type value) throws IOException {
+ value.decode(content);
+ }
+
+ /**
+ * See avove.
+ */
+ public static void decode(ByteBuffer content, Asn1Type value) throws IOException {
+ value.decode(content);
+ }
+
+ /**
+ * Parse content and return parse result. Note this is different from decode,
+ * as it doesn't decode into values, only parse result info like offset,
+ * header len, body len and etc. are out.
+ * @param content
+ * @return
+ * @throws IOException
+ */
+ public static Asn1ParseResult parse(byte[] content) throws IOException {
+ return parse(ByteBuffer.wrap(content));
+ }
+
+ /**
+ * See avove.
+ */
+ public static Asn1ParseResult parse(ByteBuffer content) throws IOException {
+ return Asn1Parser.parse(content);
+ }
+
+ /**
+ * Dump out a value.
+ * @param value
+ */
+ public static void dump(Asn1Type value) {
+ Asn1Dumper dumper = new Asn1Dumper();
+ dumper.dumpType(0, value);
+ String output = dumper.output();
+ System.out.println(output);
+ }
+
+ /**
+ * Parse first, and then dump out the parse result.
+ * @param hexStr
+ * @throws IOException
+ */
+ public static void parseAndDump(String hexStr) throws IOException {
+ byte[] data = HexUtil.hex2bytes(hexStr);
+ parseAndDump(data);
+ }
+
+ /**
+ * See avove.
+ */
+ public static void parseAndDump(ByteBuffer content) throws IOException {
+ byte[] bytes = new byte[content.remaining()];
+ content.get(bytes);
+ parseAndDump(bytes);
+ }
+
+ /**
+ * See avove.
+ */
+ public static void parseAndDump(byte[] content) throws IOException {
+ String hexStr = HexUtil.bytesToHex(content);
+ Asn1Dumper dumper = new Asn1Dumper();
+ System.out.println("Dumping data:");
+ dumper.dumpData(hexStr);
+ dumper.parseAndDump(content);
+ String output = dumper.output();
+ System.out.println(output);
+ }
+
+ /**
+ * Decode first, and then dump out the decoded value.
+ * @param hexStr
+ * @throws IOException
+ */
+ public static void decodeAndDump(String hexStr) throws IOException {
+ byte[] data = HexUtil.hex2bytes(hexStr);
+ decodeAndDump(data);
+ }
+
+ /**
+ * See avove.
+ */
+ public static void decodeAndDump(ByteBuffer content) throws IOException {
+ byte[] bytes = new byte[content.remaining()];
+ content.get(bytes);
+ decodeAndDump(bytes);
+ }
+
+ /**
+ * See avove.
+ */
+ public static void decodeAndDump(byte[] content) throws IOException {
+ String hexStr = HexUtil.bytesToHex(content);
+ Asn1Dumper dumper = new Asn1Dumper();
+ System.out.println("Dumping data:");
+ dumper.dumpData(hexStr);
+ dumper.decodeAndDump(content);
+ String output = dumper.output();
+ System.out.println(output);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Binder.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Binder.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Binder.java
new file mode 100644
index 0000000..c73b63a
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Binder.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;
+
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+import org.apache.kerby.asn1.type.Asn1Encodeable;
+import org.apache.kerby.asn1.type.Asn1Type;
+
+import java.io.IOException;
+
+/**
+ * Decode and bind a parsing result to an ASN1 object.
+ */
+public final class Asn1Binder {
+
+ private Asn1Binder() {
+
+ }
+
+ public static void bind(Asn1ParseResult parseResult,
+ Asn1Type value) throws IOException {
+ value.useDefinitiveLength(parseResult.isDefinitiveLength());
+ ((Asn1Encodeable) value).decode(parseResult);
+ }
+
+ public static void bindWithTagging(Asn1ParseResult parseResult, Asn1Type value,
+ TaggingOption taggingOption) throws IOException {
+ if (!parseResult.isTagSpecific()) {
+ throw new IllegalArgumentException(
+ "Attempting to decode non-tagged value using tagging way");
+ }
+ ((Asn1Encodeable) value).taggedDecode(parseResult, taggingOption);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Converter.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Converter.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Converter.java
new file mode 100644
index 0000000..f426764
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Converter.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;
+
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+import org.apache.kerby.asn1.type.Asn1Specific;
+import org.apache.kerby.asn1.type.Asn1Collection;
+import org.apache.kerby.asn1.type.Asn1Constructed;
+import org.apache.kerby.asn1.type.Asn1Encodeable;
+import org.apache.kerby.asn1.type.Asn1Simple;
+import org.apache.kerby.asn1.type.Asn1Type;
+
+import java.io.IOException;
+
+/**
+ * Converting a ASN1 parsing result into an ASN1 object.
+ */
+public final class Asn1Converter {
+
+ private Asn1Converter() {
+
+ }
+
+ public static Asn1Type convert(Asn1ParseResult parseResult,
+ boolean isLazy) throws IOException {
+ if (Asn1Simple.isSimple(parseResult.tag())) {
+ return Asn1Converter.convertAsSimple(parseResult);
+ } else if (Asn1Collection.isCollection(parseResult.tag())) {
+ return Asn1Converter.convertAsCollection(parseResult, isLazy);
+ } else if (!parseResult.tag().isPrimitive()) {
+ Asn1Encodeable tmpValue = new Asn1Constructed(parseResult.tag());
+ tmpValue.decode(parseResult);
+ return tmpValue;
+ } else if (parseResult.isTagSpecific()) {
+ Asn1Specific app = new Asn1Specific(parseResult.tag());
+ app.decode(parseResult);
+ return app;
+ } else {
+ throw new IOException("Unexpected item: " + parseResult.simpleInfo());
+ }
+ }
+
+ public static Asn1Type convertAsSimple(Asn1ParseResult parseResult) throws IOException {
+ Asn1Encodeable value = Asn1Simple.createSimple(parseResult.tagNo());
+ value.useDefinitiveLength(parseResult.isDefinitiveLength());
+ Asn1Binder.bind(parseResult, value);
+ return value;
+ }
+
+ public static Asn1Type convertAsCollection(Asn1ParseResult parseResult,
+ boolean isLazy) throws IOException {
+ Asn1Collection value = Asn1Collection.createCollection(parseResult.tag());
+ value.useDefinitiveLength(parseResult.isDefinitiveLength());
+ value.setLazy(isLazy);
+ Asn1Binder.bind(parseResult, value);
+ return value;
+ }
+
+ public static Asn1Type convertAs(Asn1ParseResult parseResult,
+ Class<? extends Asn1Type> type) throws IOException {
+ Asn1Type value;
+ try {
+ value = type.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid type: "
+ + type.getCanonicalName(), e);
+ }
+ Asn1Binder.bind(parseResult, value);
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
new file mode 100644
index 0000000..d4ae6d9
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
@@ -0,0 +1,26 @@
+/**
+ * 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;
+
+public interface Asn1Dumpable {
+
+ void dumpWith(Asn1Dumper dumper, int indents);
+
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java
new file mode 100644
index 0000000..3368a44
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java
@@ -0,0 +1,136 @@
+/**
+ * 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;
+
+import org.apache.kerby.asn1.parse.Asn1Item;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+import org.apache.kerby.asn1.parse.Asn1Parser;
+import org.apache.kerby.asn1.type.Asn1Specific;
+import org.apache.kerby.asn1.type.Asn1Simple;
+import org.apache.kerby.asn1.type.Asn1Type;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public final class Asn1Dumper {
+ private StringBuilder builder = new StringBuilder();
+
+ public String output() {
+ return builder.toString();
+ }
+
+ public void parseAndDump(byte[] content) throws IOException {
+ parseAndDump(ByteBuffer.wrap(content));
+ }
+
+ public void decodeAndDump(byte[] content) throws IOException {
+ decodeAndDump(ByteBuffer.wrap(content));
+ }
+
+ public void decodeAndDump(ByteBuffer content) throws IOException {
+ Asn1Type value = Asn1.decode(content);
+ dumpType(0, value);
+ }
+
+ public void parseAndDump(ByteBuffer content) throws IOException {
+ Asn1ParseResult parseResult = Asn1Parser.parse(content);
+ dumpParseResult(0, parseResult);
+ }
+
+ public void dumpType(Asn1Type value) {
+ dumpType(0, value);
+ }
+
+ public Asn1Dumper dumpType(int indents, Asn1Type value) {
+ if (value == null) {
+ indent(indents).append("Null");
+ } else if (value instanceof Asn1Simple) {
+ indent(indents).append(value.toString());
+ } else if (value instanceof Asn1Dumpable) {
+ Asn1Dumpable dumpable = (Asn1Dumpable) value;
+ dumpable.dumpWith(this, indents);
+ } else if (value instanceof Asn1Specific) {
+ indent(indents).append(value.toString());
+ } else {
+ indent(indents).append("<Unknown>");
+ }
+
+ return this;
+ }
+
+ public Asn1Dumper dumpParseResult(int indents, Asn1ParseResult value) {
+ if (value == null) {
+ indent(indents).append("Null");
+ } else if (value instanceof Asn1Item) {
+ indent(indents).append(value.toString());
+ } else if (value instanceof Asn1Dumpable) {
+ Asn1Dumpable dumpable = (Asn1Dumpable) value;
+ dumpable.dumpWith(this, indents);
+ } else {
+ indent(indents).append("<Unknown>");
+ }
+
+ return this;
+ }
+
+ public Asn1Dumper indent(int numSpaces) {
+ for (int i = 0; i < numSpaces; i++) {
+ builder.append(' ');
+ }
+ return this;
+ }
+
+ public Asn1Dumper append(Asn1Simple<?> simpleValue) {
+ if (simpleValue != null) {
+ builder.append(simpleValue.toString());
+ } else {
+ builder.append("null");
+ }
+ return this;
+ }
+
+ public Asn1Dumper append(String string) {
+ builder.append(string);
+ return this;
+ }
+
+ public Asn1Dumper appendType(Class<?> cls) {
+ builder.append("<").append(cls.getSimpleName()).append("> ");
+ return this;
+ }
+
+ public Asn1Dumper newLine() {
+ builder.append("\n");
+ return this;
+ }
+
+ public Asn1Dumper dumpData(String hexData) {
+ int range = 100;
+ int pos = range;
+
+ while (pos < hexData.length()) {
+ System.out.println(hexData.substring(pos - range, pos));
+ pos = pos + range;
+ }
+ System.out.println(hexData.substring(pos - range, hexData.length()));
+
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Factory.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Factory.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Factory.java
new file mode 100644
index 0000000..7610751
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Factory.java
@@ -0,0 +1,57 @@
+/**
+ * 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;
+
+import org.apache.kerby.asn1.type.Asn1Collection;
+import org.apache.kerby.asn1.type.Asn1Simple;
+import org.apache.kerby.asn1.type.Asn1Type;
+
+/**
+ * ASN1 type factory
+ */
+public class Asn1Factory {
+
+ /**
+ * Create an ASN1 type with specified tag number
+ * @param tagNo The tag number
+ * @return ASN1 type
+ */
+ public static Asn1Type create(int tagNo) {
+ UniversalTag tagNoEnum = UniversalTag.fromValue(tagNo);
+ if (tagNoEnum != UniversalTag.UNKNOWN) {
+ return create(tagNoEnum);
+ }
+ throw new IllegalArgumentException("Unexpected tag " + tagNo);
+ }
+
+ /**
+ * Create an ASN1 type with specified tag
+ * @param tagNo The tag number
+ * @return ASN1 type
+ */
+ public static Asn1Type create(UniversalTag tagNo) {
+ if (Asn1Simple.isSimple(tagNo)) {
+ return Asn1Simple.createSimple(tagNo);
+ } else if (Asn1Collection.isCollection(tagNo)) {
+ return Asn1Collection.createCollection(tagNo);
+ }
+ throw new IllegalArgumentException("Unexpected tag " + tagNo);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
new file mode 100644
index 0000000..72182b0
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
@@ -0,0 +1,107 @@
+/**
+ * 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;
+
+import org.apache.kerby.asn1.type.Asn1Type;
+
+/**
+ * Representing a field in a ASN1 collection or choice.
+ */
+public class Asn1FieldInfo {
+ private EnumType index;
+ private int tagNo = -1; // Indicate a non-tagged field
+ private boolean isImplicit;
+ private Class<? extends Asn1Type> type;
+
+ /**
+ * Constructor for a tagged field, the tagNo being the same of index.
+ * @param index
+ * @param type
+ * @param isImplicit
+ */
+ public Asn1FieldInfo(EnumType index, Class<? extends Asn1Type> type,
+ boolean isImplicit) {
+ this(index, index.getValue(), type, isImplicit);
+ }
+
+ /**
+ * Constructor for a tagged field.
+ * @param index
+ * @param tagNo
+ * @param type
+ * @param isImplicit
+ */
+ public Asn1FieldInfo(EnumType index, int tagNo, Class<? extends Asn1Type> type,
+ boolean isImplicit) {
+ this.index = index;
+ this.tagNo = tagNo;
+ this.type = type;
+ this.isImplicit = isImplicit;
+ }
+
+ /**
+ * Constructor for a non-tagged field.
+ * @param index
+ * @param type
+ */
+ public Asn1FieldInfo(EnumType index, Class<? extends Asn1Type> type) {
+ this.index = index;
+ this.type = type;
+ this.tagNo = -1; // Indicate a non-tagged field
+ }
+
+ 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 EnumType getIndex() {
+ return index;
+ }
+
+ public boolean isImplicit() {
+ return isImplicit;
+ }
+
+ public Asn1Type createFieldValue() {
+ try {
+ return type.newInstance();
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ "Bad field type provided, no default constructor?", e);
+ }
+ }
+
+ public Tag getFieldTag() {
+ Asn1Type fieldValue = createFieldValue();
+ return fieldValue.tag();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java
new file mode 100644
index 0000000..e0166ec
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.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;
+
+/**
+ * A helper interface used by Asn1Enumerated.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface EnumType {
+ /**
+ * @return the Enum element value
+ */
+ int getValue();
+
+ /**
+ * @return The enum element name
+ */
+ String getName();
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java
new file mode 100644
index 0000000..7142dc0
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.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;
+
+import org.apache.kerby.asn1.type.Asn1Type;
+
+/**
+ * Representing an explicitly tagged field in a ASN1 collection or choice.
+ */
+public class ExplicitField extends Asn1FieldInfo {
+
+ /**
+ * Constructor for an explicitly tagged field.
+ * @param index
+ * @param type
+ */
+ public ExplicitField(EnumType index, int tagNo, Class<? extends Asn1Type> type) {
+ super(index, tagNo, type, false);
+ }
+
+ /**
+ * Constructor for an explicitly tagged field, the tagNo being the same of index.
+ * @param index
+ * @param type
+ */
+ public ExplicitField(EnumType index, Class<? extends Asn1Type> type) {
+ super(index, index.getValue(), type, false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java
new file mode 100644
index 0000000..f488847
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.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;
+
+import org.apache.kerby.asn1.type.Asn1Type;
+
+/**
+ * Representing an implicitly tagged field in a ASN1 collection or choice.
+ */
+public class ImplicitField extends Asn1FieldInfo {
+
+ /**
+ * Constructor for an implicitly tagged field.
+ * @param index
+ * @param type
+ */
+ public ImplicitField(EnumType index, int tagNo, Class<? extends Asn1Type> type) {
+ super(index, tagNo, type, true);
+ }
+
+ /**
+ * Constructor for an implicitly tagged field, the tagNo being the same of index.
+ * @param index
+ * @param type
+ */
+ public ImplicitField(EnumType index, Class<? extends Asn1Type> type) {
+ super(index, index.getValue(), type, true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
new file mode 100644
index 0000000..d248802
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
@@ -0,0 +1,160 @@
+/**
+ * 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;
+
+/**
+ * ASN1, a tagged system.
+ */
+public class Tag {
+ private int tagFlags = 0;
+ private int tagNo = 0;
+
+ public Tag(int tag) {
+ this.tagFlags = tag & 0xE0;
+ this.tagNo = tag & 0x1F;
+ }
+
+ public Tag(UniversalTag tag) {
+ this.tagFlags = TagClass.UNIVERSAL.getValue();
+ this.tagNo = tag.getValue();
+ }
+
+ public Tag(int tagFlags, int tagNo) {
+ this.tagFlags = tagFlags & 0xE0;
+ this.tagNo = tagNo;
+ }
+
+ public Tag(TagClass tagClass, int tagNo) {
+ this.tagFlags = tagClass.getValue();
+ this.tagNo = tagNo;
+ }
+
+ public Tag(Tag other) {
+ this(other.tagFlags, other.tagNo);
+ }
+
+ public TagClass tagClass() {
+ return TagClass.fromTag(tagFlags);
+ }
+
+ public void usePrimitive(boolean isPrimitive) {
+ if (isPrimitive) {
+ tagFlags &= ~0x20;
+ } else {
+ tagFlags |= 0x20;
+ }
+ }
+
+ public boolean isPrimitive() {
+ return (tagFlags & 0x20) == 0;
+ }
+
+ public int tagFlags() {
+ return tagFlags;
+ }
+
+ public int tagNo() {
+ return tagNo;
+ }
+
+ public UniversalTag universalTag() {
+ if (isUniversal()) {
+ return UniversalTag.fromValue(tagNo());
+ }
+ return UniversalTag.UNKNOWN;
+ }
+
+ public boolean isEOC() {
+ return universalTag() == UniversalTag.EOC;
+ }
+
+ public boolean isNull() {
+ return universalTag() == UniversalTag.NULL;
+ }
+
+ public boolean isUniversal() {
+ return tagClass().isUniversal();
+ }
+
+ public boolean isAppSpecific() {
+ return tagClass().isAppSpecific();
+ }
+
+ public boolean isContextSpecific() {
+ return tagClass().isContextSpecific();
+ }
+
+ public boolean isSpecific() {
+ return tagClass().isSpecific();
+ }
+
+ public byte tagByte() {
+ int n = tagFlags | (tagNo < 0x1F ? tagNo : 0x1F);
+ return (byte) (n & 0xFF);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Tag tag = (Tag) o;
+
+ if (tagFlags != tag.tagFlags) {
+ return false;
+ }
+
+ return tagNo == tag.tagNo;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = tagFlags;
+ result = 31 * result + tagNo;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("0x%02X", tagByte());
+ }
+
+ public String typeStr() {
+ if (isUniversal()) {
+ return universalTag().toStr();
+ } else if (isAppSpecific()) {
+ return "application [" + tagNo() + "]";
+ } else {
+ return "context [" + tagNo() + "]";
+ }
+ }
+
+ public static Tag newAppTag(int tagNo) {
+ return new Tag(TagClass.APPLICATION, tagNo);
+ }
+
+ public static Tag newCtxTag(int tagNo) {
+ return new Tag(TagClass.CONTEXT_SPECIFIC, tagNo);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TagClass.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TagClass.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TagClass.java
new file mode 100644
index 0000000..8d02917
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TagClass.java
@@ -0,0 +1,99 @@
+/**
+ * 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;
+
+/**
+ * Tag class defined by the spec.
+ */
+public enum TagClass {
+ UNKNOWN(-1),
+ UNIVERSAL(0x00),
+ APPLICATION(0x40),
+ CONTEXT_SPECIFIC(0x80),
+ PRIVATE(0xC0);
+
+ private int value;
+
+ /**
+ * The constructor given the value.
+ * @param value
+ */
+ private TagClass(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the tag class value.
+ * @return value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Tell it's universal or not.
+ * @return true if it's universal otherwise false
+ */
+ public boolean isUniversal() {
+ return this == UNIVERSAL;
+ }
+
+ public boolean isAppSpecific() {
+ return this == APPLICATION;
+ }
+
+ public boolean isContextSpecific() {
+ return this == CONTEXT_SPECIFIC;
+ }
+
+ public boolean isSpecific() {
+ return this == APPLICATION || this == CONTEXT_SPECIFIC;
+ }
+
+ /**
+ * Converted from an integer
+ * @param value The int value of tag class
+ * @return tag class
+ */
+ public static TagClass fromValue(int value) {
+ // Optimized by Emmanuel
+ switch (value) {
+ case 0x00:
+ return TagClass.UNIVERSAL;
+ case 0x40:
+ return TagClass.APPLICATION;
+ case 0x80:
+ return TagClass.CONTEXT_SPECIFIC;
+ case 0xC0:
+ return TagClass.PRIVATE;
+ default:
+ return TagClass.UNKNOWN;
+ }
+ }
+
+ /**
+ * Converted from a tag value, which contains tag class info.
+ * @param tag The int value of tag class
+ * @return tag class
+ */
+ public static TagClass fromTag(int tag) {
+ return fromValue(tag & 0xC0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TaggingOption.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TaggingOption.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TaggingOption.java
new file mode 100644
index 0000000..154e1ab
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/TaggingOption.java
@@ -0,0 +1,119 @@
+/**
+ * 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;
+
+/**
+ * Tagging option for tagging an ASN1 type.
+ */
+public final class TaggingOption {
+ /** The tag number. We limit it to an int, although it's theorically unlimited */
+ private int tagNo;
+
+ /** A flag set to TRUE when the tag is IMPLICIT */
+ private boolean isImplicit;
+
+ /** A flag set to TRUE when the tag is an APPLICATION tag */
+ private boolean isAppSpecific;
+
+ /**
+ * Create an implicit application specific tagging option with tagNo.
+ * @param tagNo The tag number
+ * @return tagging option
+ */
+ public static TaggingOption newImplicitAppSpecific(int tagNo) {
+ return new TaggingOption(tagNo, true, true);
+ }
+
+ /**
+ * Create an explicit application specific tagging option with tagNo.
+ * @param tagNo The tag number
+ * @return tagging option
+ */
+ public static TaggingOption newExplicitAppSpecific(int tagNo) {
+ return new TaggingOption(tagNo, false, true);
+ }
+
+ /**
+ * Create an implicit context specific tagging option with tagNo.
+ * @param tagNo The tag number
+ * @return tagging option
+ */
+ public static TaggingOption newImplicitContextSpecific(int tagNo) {
+ return new TaggingOption(tagNo, true, false);
+ }
+
+ /**
+ * Create an explicit context specific tagging option with tagNo.
+ * @param tagNo The tag number
+ * @return tagging option
+ */
+ public static TaggingOption newExplicitContextSpecific(int tagNo) {
+ return new TaggingOption(tagNo, false, false);
+ }
+
+ /**
+ * The private constructor.
+ * @param tagNo The tag number
+ * @param isImplicit Implicit or not
+ * @param isAppSpecific App specific or not
+ */
+ private TaggingOption(int tagNo, boolean isImplicit, boolean isAppSpecific) {
+ this.tagNo = tagNo;
+ this.isImplicit = isImplicit;
+ this.isAppSpecific = isAppSpecific;
+ }
+
+ /**
+ * Make tag giving it's tagged constructed.
+ * @param isTaggedConstructed Tagged constructed or not
+ * @return tag
+ */
+ public Tag getTag(boolean isTaggedConstructed) {
+ boolean isConstructed = isImplicit ? isTaggedConstructed : true;
+ TagClass tagClass = isAppSpecific ? TagClass.APPLICATION : TagClass.CONTEXT_SPECIFIC;
+ int flags = tagClass.getValue() | (isConstructed ? 0x20 : 0x00);
+
+ return new Tag(flags, tagNo);
+ }
+
+ /**
+ * Get the tag number.
+ * @return tag number
+ */
+ public int getTagNo() {
+ return tagNo;
+ }
+
+ /**
+ * Tell it's application specific or not.
+ * @return true if it's application specific otherwise false
+ */
+ public boolean isAppSpecific() {
+ return isAppSpecific;
+ }
+
+ /**
+ * Tell it's implicit or not.
+ * @return true if it's implicit otherwise false
+ */
+ public boolean isImplicit() {
+ return isImplicit;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
new file mode 100644
index 0000000..3fc5026
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
@@ -0,0 +1,132 @@
+/**
+ * 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;
+
+/**
+ * An enumeration for every ASN.1 UNIVERSAL type.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum UniversalTag {
+ UNKNOWN (-1),
+ CHOICE (-2), // Only for internal using
+ ANY (-3), // Only for internal using
+ EOC (0), // End of content, use by BER
+ BOOLEAN (0x01),
+ INTEGER (0x02),
+ BIT_STRING (0x03),
+ OCTET_STRING (0x04),
+ NULL (0x05),
+ OBJECT_IDENTIFIER (0x06),
+ OBJECT_DESCRIPTOR (0x07),
+ EXTERNAL (0x08),
+ REAL (0x09),
+ ENUMERATED (0x0a),
+ EMBEDDED_PDV (0x0b),
+ UTF8_STRING (0x0c),
+ RELATIVE_OID (0x0d),
+ RESERVED_14 (0x0e),
+ RESERVED_15 (0x0f),
+ SEQUENCE (0x10),
+ SEQUENCE_OF (0x10),
+ SET (0x11),
+ SET_OF (0x11),
+ NUMERIC_STRING (0x12),
+ PRINTABLE_STRING (0x13),
+ T61_STRING (0x14),
+ VIDEOTEX_STRING (0x15),
+ IA5_STRING (0x16),
+ UTC_TIME (0x17),
+ GENERALIZED_TIME (0x18),
+ GRAPHIC_STRING (0x19),
+ VISIBLE_STRING (0x1a),
+ GENERAL_STRING (0x1b),
+ UNIVERSAL_STRING (0x1c),
+ CHARACTER_STRING (0x1d),
+ BMP_STRING (0x1e),
+ RESERVED_31 (0x1f);
+
+ /** The tag value */
+ private int value;
+
+ /**
+ * Create an instance of this class
+ */
+ private UniversalTag(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return The associated tag value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Retrieve the UniversalTag associated with a given value
+ * @param value The integer value
+ * @return The associated UniversalTag
+ */
+ public static UniversalTag fromValue(int value) {
+ switch (value) {
+ case -2 : return CHOICE;
+ case 0x00 : return EOC;
+ case 0x01 : return BOOLEAN;
+ case 0x02 : return INTEGER;
+ case 0x03 : return BIT_STRING;
+ case 0x04 : return OCTET_STRING;
+ case 0x05 : return NULL;
+ case 0x06 : return OBJECT_IDENTIFIER;
+ case 0x07 : return OBJECT_DESCRIPTOR;
+ case 0x08 : return EXTERNAL;
+ case 0x09 : return REAL;
+ case 0x0A : return ENUMERATED;
+ case 0x0B : return EMBEDDED_PDV;
+ case 0x0C : return UTF8_STRING;
+ case 0x0D : return RELATIVE_OID;
+ case 0x0E : return RESERVED_14;
+ case 0x0F : return RESERVED_15;
+ case 0x10 : return SEQUENCE;
+ case 0x11 : return SET;
+ case 0x12 : return NUMERIC_STRING;
+ case 0x13 : return PRINTABLE_STRING;
+ case 0x14 : return T61_STRING;
+ case 0x15 : return VIDEOTEX_STRING;
+ case 0x16 : return IA5_STRING;
+ case 0x17 : return UTC_TIME;
+ case 0x18 : return GENERALIZED_TIME;
+ case 0x19 : return GRAPHIC_STRING;
+ case 0x1A : return VISIBLE_STRING;
+ case 0x1B : return GENERAL_STRING;
+ case 0x1C : return UNIVERSAL_STRING;
+ case 0x1D : return CHARACTER_STRING;
+ case 0x1E : return BMP_STRING;
+ case 0x1F : return RESERVED_31;
+ default : return UNKNOWN;
+ }
+ }
+
+ public String toStr() {
+ String typeStr = toString();
+ typeStr = typeStr.replace('_', ' ');
+ return typeStr.toLowerCase();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
new file mode 100644
index 0000000..d52b63f
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
@@ -0,0 +1,81 @@
+/**
+ * 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.parse;
+
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ASN1 constructed types, mainly structured ones, but also some primitive ones.
+ */
+public class Asn1Container
+ extends Asn1ParseResult implements Asn1Dumpable {
+
+ private List<Asn1ParseResult> children = new ArrayList<>();
+
+ public Asn1Container(Asn1Header header, int bodyStart, ByteBuffer buffer) {
+ super(header, bodyStart, buffer);
+ }
+
+ public List<Asn1ParseResult> getChildren() {
+ return children;
+ }
+
+ public void addItem(Asn1ParseResult value) {
+ children.add(value);
+ }
+
+ public void clear() {
+ children.clear();
+ }
+
+ @Override
+ public void dumpWith(Asn1Dumper dumper, int indents) {
+ dumper.indent(indents).append(toString());
+ if (children.size() > 0) {
+ dumper.newLine();
+ }
+
+ int i = children.size();
+ for (Asn1ParseResult aObj : children) {
+ dumper.dumpParseResult(indents + 4, aObj);
+ i--;
+ if (i > 0) {
+ dumper.newLine();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String typeStr = tag().typeStr();
+ typeStr += " ["
+ + "tag=" + tag()
+ + ", off=" + getOffset()
+ + ", len=" + getHeaderLength() + "+" + getBodyLength()
+ + (isDefinitiveLength() ? "" : "(undefined)")
+ + "]";
+ return typeStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java
new file mode 100644
index 0000000..41db80e
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.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.parse;
+
+import org.apache.kerby.asn1.Tag;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Combine multiple parts in a container into a single item, for primitive types
+ * that use constructed encoding.
+ */
+public class Asn1DerivedItem extends Asn1Item {
+
+ private final Asn1Container container;
+ private final Tag newTag;
+ private int newBodyLength;
+ private ByteBuffer newBodyBuffer;
+
+ public Asn1DerivedItem(Tag newTag, Asn1Container container) {
+ super(container.getHeader(), container.getBodyStart(),
+ container.getBuffer());
+
+ this.newTag = newTag;
+ this.container = container;
+ this.newBodyLength = -1;
+ }
+
+ @Override
+ public Tag tag() {
+ return newTag;
+ }
+
+ private int computeBodyLength() {
+ int totalLen = 0;
+ for (Asn1ParseResult parseItem : container.getChildren()) {
+ totalLen += parseItem.getBodyLength();
+ }
+
+ return totalLen;
+ }
+
+ private ByteBuffer makeBodyBuffer() {
+ ByteBuffer tmpBuffer = ByteBuffer.allocate(getBodyLength());
+ for (Asn1ParseResult parseItem : container.getChildren()) {
+ tmpBuffer.put(parseItem.getBodyBuffer());
+ }
+ tmpBuffer.flip();
+
+ return tmpBuffer;
+ }
+
+ @Override
+ public ByteBuffer getBodyBuffer() {
+ if (newBodyBuffer == null) {
+ newBodyBuffer = makeBodyBuffer();
+ }
+ return newBodyBuffer;
+ }
+
+ @Override
+ public int getBodyLength() {
+ if (newBodyLength == -1) {
+ newBodyLength = computeBodyLength();
+ }
+
+ return newBodyLength;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java
new file mode 100644
index 0000000..8d90ac1
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.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.parse;
+
+import org.apache.kerby.asn1.Tag;
+
+public class Asn1Header {
+ private Tag tag;
+ private int length;
+
+ public Asn1Header(Tag tag, int length) {
+ this.tag = tag;
+ this.length = length;
+ }
+
+ public Tag getTag() {
+ return tag;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public boolean isEOC() {
+ return length == 0 && tag.isEOC();
+ }
+
+ public boolean isDefinitiveLength() {
+ return length != -1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
new file mode 100644
index 0000000..066d0aa
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
@@ -0,0 +1,34 @@
+/**
+ * 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.parse;
+
+import java.nio.ByteBuffer;
+
+public class Asn1Item extends Asn1ParseResult {
+
+ public Asn1Item(Asn1Header header, int bodyStart, ByteBuffer buffer) {
+ super(header, bodyStart, buffer);
+ }
+
+ @Override
+ public String toString() {
+ return simpleInfo();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
new file mode 100644
index 0000000..0152cfc
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
@@ -0,0 +1,124 @@
+/**
+ * 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.parse;
+
+import org.apache.kerby.asn1.type.Asn1Object;
+import org.apache.kerby.asn1.util.Asn1Util;
+
+import java.nio.ByteBuffer;
+
+public abstract class Asn1ParseResult extends Asn1Object {
+ private Asn1Header header;
+ private int bodyStart;
+ private int bodyEnd;
+ private ByteBuffer buffer;
+
+ public Asn1ParseResult(Asn1Header header,
+ int bodyStart, ByteBuffer buffer) {
+ super(header.getTag());
+ this.header = header;
+ this.bodyStart = bodyStart;
+ this.buffer = buffer;
+
+ this.bodyEnd = isDefinitiveLength() ? bodyStart + header.getLength() : -1;
+ }
+
+ public Asn1Header getHeader() {
+ return header;
+ }
+
+ public int getBodyStart() {
+ return bodyStart;
+ }
+
+ public int getBodyEnd() {
+ return bodyEnd;
+ }
+
+ public void setBodyEnd(int bodyEnd) {
+ this.bodyEnd = bodyEnd;
+ }
+
+ public ByteBuffer getBuffer() {
+ return buffer;
+ }
+
+ public ByteBuffer getBodyBuffer() {
+ ByteBuffer result = buffer.duplicate();
+ result.position(bodyStart);
+
+ int end = getBodyEnd();
+ if (end >= bodyStart) {
+ result.limit(end);
+ }
+
+ return result;
+ }
+
+ public byte[] readBodyBytes() {
+ ByteBuffer bodyBuffer = getBodyBuffer();
+ byte[] result = new byte[bodyBuffer.remaining()];
+ bodyBuffer.get(result);
+ return result;
+ }
+
+ public boolean isDefinitiveLength() {
+ return header.isDefinitiveLength();
+ }
+
+ public int getEncodingLength() {
+ return getHeaderLength() + getBodyLength();
+ }
+
+ public int getHeaderLength() {
+ int bodyLen = getBodyLength();
+ int headerLen = Asn1Util.lengthOfTagLength(header.getTag().tagNo());
+ headerLen += (header.isDefinitiveLength()
+ ? Asn1Util.lengthOfBodyLength(bodyLen) : 1);
+ return headerLen;
+ }
+
+ public int getOffset() {
+ return getBodyStart() - getHeaderLength();
+ }
+
+ public int getBodyLength() {
+ if (isDefinitiveLength()) {
+ return header.getLength();
+ } else if (getBodyEnd() != -1) {
+ return getBodyEnd() - getBodyStart();
+ }
+ return -1;
+ }
+
+
+ public boolean checkBodyFinished(int pos) {
+ return getBodyEnd() != -1 && pos >= getBodyEnd();
+ }
+
+ @Override
+ public String simpleInfo() {
+ return tag().typeStr() + " ["
+ + "tag=" + tag()
+ + ", off=" + getOffset()
+ + ", len=" + getHeaderLength() + "+" + getBodyLength()
+ + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
new file mode 100644
index 0000000..ff90719
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
@@ -0,0 +1,85 @@
+/**
+ * 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.parse;
+
+import org.apache.kerby.asn1.Tag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 parser.
+ */
+public class Asn1Parser {
+
+ public static void parse(Asn1Container container) throws IOException {
+ Asn1Reader reader = new Asn1Reader(container.getBuffer());
+ int pos = container.getBodyStart();
+ while (true) {
+ reader.setPosition(pos);
+ Asn1ParseResult asn1Obj = parse(reader);
+ if (asn1Obj == null) {
+ break;
+ }
+
+ container.addItem(asn1Obj);
+
+ pos += asn1Obj.getEncodingLength();
+ if (asn1Obj.isEOC()) {
+ break;
+ }
+
+ if (container.checkBodyFinished(pos)) {
+ break;
+ }
+ }
+
+ container.setBodyEnd(pos);
+ }
+
+ public static Asn1ParseResult parse(ByteBuffer content) throws IOException {
+ Asn1Reader reader = new Asn1Reader(content);
+ return parse(reader);
+ }
+
+ public static Asn1ParseResult parse(Asn1Reader reader) throws IOException {
+ if (!reader.available()) {
+ return null;
+ }
+
+ Asn1Header header = reader.readHeader();
+ Tag tmpTag = header.getTag();
+ int bodyStart = reader.getPosition();
+ Asn1ParseResult parseResult;
+
+ if (tmpTag.isPrimitive()) {
+ parseResult = new Asn1Item(header, bodyStart, reader.getBuffer());
+ } else {
+ Asn1Container container = new Asn1Container(header,
+ bodyStart, reader.getBuffer());
+ if (header.getLength() != 0) {
+ parse(container);
+ }
+ parseResult = container;
+ }
+
+ return parseResult;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
new file mode 100644
index 0000000..89994f8
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
@@ -0,0 +1,126 @@
+/**
+ * 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.parse;
+
+import org.apache.kerby.asn1.Tag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 reader for positional reading.
+ */
+public final class Asn1Reader {
+ private ByteBuffer buffer;
+ private int position;
+
+ public ByteBuffer getBuffer() {
+ return buffer;
+ }
+
+ public Asn1Header readHeader() throws IOException {
+ Tag tag = readTag();
+ int valueLength = readLength();
+ Asn1Header header = new Asn1Header(tag, valueLength);
+ return header;
+ }
+
+ public Asn1Reader(ByteBuffer buffer) {
+ this.buffer = buffer;
+ this.position = buffer.position();
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(int position) {
+ this.position = position;
+ }
+
+ public boolean available() {
+ return position < buffer.limit();
+ }
+
+ protected byte readByte() throws IOException {
+ return buffer.get(position++);
+ }
+
+ private Tag readTag() throws IOException {
+ int tagFlags = readTagFlags();
+ int tagNo = readTagNo(tagFlags);
+ return new Tag(tagFlags, tagNo);
+ }
+
+ private int readTagFlags() throws IOException {
+ int tagFlags = readByte() & 0xff;
+ return tagFlags;
+ }
+
+ private int readTagNo(int tagFlags) throws IOException {
+ int tagNo = tagFlags & 0x1f;
+
+ if (tagNo == 0x1f) {
+ tagNo = 0;
+
+ int b = readByte() & 0xff;
+ if ((b & 0x7f) == 0) {
+ throw new IOException("Invalid high tag number found");
+ }
+
+ while (b >= 0 && (b & 0x80) != 0) {
+ tagNo |= b & 0x7f;
+ tagNo <<= 7;
+ b = readByte();
+ }
+
+ tagNo |= b & 0x7f;
+ }
+
+ return tagNo;
+ }
+
+ private int readLength() throws IOException {
+ int result = readByte() & 0xff;
+ if (result == 0x80) {
+ return -1; // non-definitive length
+ }
+
+ if (result > 127) {
+ int length = result & 0x7f;
+ if (length > 4) {
+ throw new IOException("Bad length of more than 4 bytes: " + length);
+ }
+
+ result = 0;
+ int tmp;
+ for (int i = 0; i < length; i++) {
+ tmp = readByte() & 0xff;
+ result = (result << 8) + tmp;
+ }
+ }
+
+ if (result < 0) {
+ throw new IOException("Invalid length " + result);
+ }
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/AbstractAsn1Type.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/AbstractAsn1Type.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/AbstractAsn1Type.java
new file mode 100644
index 0000000..96c68a1
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/AbstractAsn1Type.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.asn1.type;
+
+import org.apache.kerby.asn1.Tag;
+import org.apache.kerby.asn1.UniversalTag;
+
+/**
+ * The abstract ASN1 type for all the ASN1 types. It provides basic
+ * encoding and decoding utilities.
+ *
+ * @param <T> the type of the value encoded/decoded or wrapped by this
+ */
+public abstract class AbstractAsn1Type<T> extends Asn1Encodeable {
+ // The wrapped real value.
+ private T value;
+
+ /**
+ * Default constructor.
+ * @param tag the tag
+ * @param value the value
+ */
+ public AbstractAsn1Type(Tag tag, T value) {
+ super(tag);
+ this.value = value;
+ }
+
+ /**
+ * Default constructor.
+ * @param tag the tag
+ */
+ public AbstractAsn1Type(Tag tag) {
+ super(tag);
+ }
+
+ /**
+ * Default constructor with an universal tag.
+ * @param tag the tag
+ * @param value the value
+ */
+ public AbstractAsn1Type(UniversalTag tag, T value) {
+ super(tag);
+ this.value = value;
+ }
+
+ /**
+ * Default constructor with an universal tag.
+ * @param tag the tag
+ */
+ public AbstractAsn1Type(UniversalTag tag) {
+ super(tag);
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public void setValue(T value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return tag().typeStr();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
new file mode 100644
index 0000000..3c35173
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
@@ -0,0 +1,212 @@
+/**
+ * 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.Asn1Binder;
+import org.apache.kerby.asn1.Asn1Converter;
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
+import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.Tag;
+import org.apache.kerby.asn1.TaggingOption;
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Can be any valid ASN-1 ojbect, limited or not limited.
+ */
+public class Asn1Any
+ extends AbstractAsn1Type<Asn1Type> implements Asn1Dumpable {
+ private Class<? extends Asn1Type> valueType;
+ private Asn1FieldInfo decodeInfo;
+ private Asn1ParseResult parseResult;
+ private boolean isBlindlyDecoded = true;
+
+ public Asn1Any() {
+ super(UniversalTag.ANY);
+ }
+
+ public Asn1Any(Asn1Type anyValue) {
+ this();
+ setValue(anyValue);
+ }
+
+ @Override
+ public Tag tag() {
+ if (getValue() != null) {
+ return getValue().tag();
+ } else if (parseResult != null) {
+ return parseResult.tag();
+ }
+ return super.tag();
+ }
+
+ public void setValueType(Class<? extends Asn1Type> valueType) {
+ this.valueType = valueType;
+ }
+
+ public void setDecodeInfo(Asn1FieldInfo decodeInfo) {
+ this.decodeInfo = decodeInfo;
+ }
+
+ public Asn1ParseResult getParseResult() {
+ return parseResult;
+ }
+
+ @Override
+ public void encode(ByteBuffer buffer) throws IOException {
+ Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+ if (theValue != null) {
+ if (!isBlindlyDecoded) {
+ if (decodeInfo.isTagged()) {
+ TaggingOption taggingOption =
+ decodeInfo.getTaggingOption();
+ theValue.taggedEncode(buffer, taggingOption);
+ } else {
+ theValue.encode(buffer);
+ }
+ } else {
+ theValue.encode(buffer);
+ }
+ }
+ }
+
+ @Override
+ public int encodingLength() {
+ Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+ if (theValue != null) {
+ if (!isBlindlyDecoded) {
+ if (decodeInfo.isTagged()) {
+ TaggingOption taggingOption =
+ decodeInfo.getTaggingOption();
+ return theValue.taggedEncodingLength(taggingOption);
+ } else {
+ return theValue.encodingLength();
+ }
+ } else {
+ return theValue.encodingLength();
+ }
+ }
+
+ return super.encodingLength();
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+ if (theValue == null) {
+ return 0;
+ }
+
+ return -1; // Indicate error, shouldn't be here.
+ }
+
+ @Override
+ public void decode(ByteBuffer content) throws IOException {
+ setValue(null);
+
+ super.decode(content);
+ }
+
+ @Override
+ public void decode(Asn1ParseResult parseResult) throws IOException {
+ // Avoid the tag checking here.
+ decodeBody(parseResult);
+ }
+
+ @Override
+ protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+ this.parseResult = parseResult;
+
+ if (valueType != null) {
+ typeAwareDecode(valueType);
+ } else {
+ blindlyDecode();
+ }
+ }
+
+ private void blindlyDecode() throws IOException {
+ Asn1Type anyValue = Asn1Converter.convert(parseResult, false);
+ if (decodeInfo != null && decodeInfo.isTagged()) {
+ // Escape the wrapper
+ Asn1Constructed constructed = (Asn1Constructed) anyValue;
+ Asn1Type innerValue = constructed.getValue().get(0);
+ setValue(innerValue);
+ } else {
+ setValue(anyValue);
+ }
+
+ isBlindlyDecoded = true;
+ }
+
+ protected <T extends Asn1Type> T getValueAs(Class<T> t) {
+ Asn1Type value = getValue();
+ if (value != null && !isBlindlyDecoded) {
+ return (T) value;
+ }
+
+ if (valueType != null && valueType != t) {
+ throw new RuntimeException("Required value type isn't the same"
+ + " with the value type set before");
+ }
+
+ try {
+ typeAwareDecode(t);
+ } catch (IOException e) {
+ throw new RuntimeException("Type aware decoding of Any type failed");
+ }
+
+ return (T) getValue();
+ }
+
+ private <T extends Asn1Type> void typeAwareDecode(Class<T> t) throws IOException {
+ T result;
+ try {
+ result = t.newInstance();
+ } catch (Exception e) {
+ throw new IOException("No default constructor?", e);
+ }
+
+ if (parseResult.isContextSpecific()) {
+ Asn1Binder.bindWithTagging(parseResult, result,
+ decodeInfo.getTaggingOption());
+ } else {
+ Asn1Binder.bind(parseResult, result);
+ }
+
+ setValue(result);
+ isBlindlyDecoded = false;
+ }
+
+ @Override
+ public void dumpWith(Asn1Dumper dumper, int indents) {
+ Asn1Type theValue = getValue();
+ dumper.indent(indents).append("<Any>").newLine();
+ //dumper.append(simpleInfo()).newLine();
+ dumper.dumpType(indents, theValue);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
new file mode 100644
index 0000000..1b921e1
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
@@ -0,0 +1,108 @@
+/**
+ * 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() {
+ byte[] body = getValue();
+ if (body != null) {
+ return body.length + 1;
+ }
+ return 0;
+ }
+
+ @Override
+ protected void toBytes() {
+ byte[] bytes = new byte[encodingBodyLength()];
+ byte[] body = getValue();
+ if (body != null) {
+ bytes[0] = (byte) padding;
+ System.arraycopy(body, 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]");
+ }
+ }
+
+ @Override
+ public String toString() {
+ String typeStr = tag().typeStr() + " ["
+ + "tag=" + tag()
+ + ", len=" + getHeaderLength() + "+" + getBodyLength()
+ + "] ";
+
+ byte[] valueBytes = getValue();
+ String valueStr = "<null>";
+ if (valueBytes != null) {
+ valueStr = "<" + valueBytes.length + " bytes>";
+ }
+
+ return typeStr + valueStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
new file mode 100644
index 0000000..294649e
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BmpString.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+
+public class Asn1BmpString extends Asn1Simple<String> {
+ public Asn1BmpString() {
+ super(UniversalTag.BMP_STRING);
+ }
+
+ public Asn1BmpString(String value) {
+ super(UniversalTag.BMP_STRING, value);
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ return getValue().length() * 2;
+ }
+
+ protected void toBytes() {
+ String strValue = getValue();
+ int len = strValue.length();
+ byte[] bytes = new byte[len * 2];
+
+ for (int i = 0; i != len; i++) {
+ char 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(Asn1ParseResult parseResult) throws IOException {
+ if (parseResult.getBodyLength() % 2 != 0) {
+ throw new IOException("Bad stream, BMP string expecting multiple of 2 bytes");
+ }
+ super.decodeBody(parseResult);
+ }
+}