2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * @author Vladimir N. Molotkov, Stepan M. Mishura
23 package org.apache.harmony.security.asn1;
25 import java.io.IOException;
29 * Implicitly tagged ASN.1 type.
31 * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
33 public class ASN1Implicit extends ASN1Type {
35 // primitive type of tagging
36 private static final int TAGGING_PRIMITIVE = 0;
38 // constructed type of tagging
39 private static final int TAGGING_CONSTRUCTED = 1;
41 // string type of tagging
42 private static final int TAGGING_STRING = 2;
45 private final ASN1Type type;
47 // type of tagging. There are three of them
48 // 1) primitive: only primitive identifier is valid
49 // 2) constructed: only constructed identifier is valid
50 // 3) string: both identifiers are valid
51 private final int taggingType;
54 * Constructs implicitly tagged ASN.1 type
55 * with context-specific tag class and specified tag number.
57 * @param tagNumber - ASN.1 tag number
58 * @param type - ASN.1 type to be tagged
59 * @throws IllegalArgumentException - if tagNumber or type is invalid
61 public ASN1Implicit(int tagNumber, ASN1Type type) {
62 this(CLASS_CONTEXTSPECIFIC, tagNumber, type);
66 * Constructs implicitly tagged ASN.1 type
68 * @param tagClass - ASN.1 tag class.
69 * @param tagNumber - ASN.1 tag number
70 * @param type - ASN.1 type to be tagged
71 * @throws IllegalArgumentException - if tagNumber, tagClass or type is invalid
73 public ASN1Implicit(int tagClass, int tagNumber, ASN1Type type) {
74 super(tagClass, tagNumber);
76 if ((type instanceof ASN1Choice) || (type instanceof ASN1Any)) {
77 // According to X.680:
78 // 'The IMPLICIT alternative shall not be used if the type
79 // defined by "Type" is an untagged choice type or an
80 // untagged open type'
81 throw new IllegalArgumentException("Implicit tagging can not be used for ASN.1 ANY or CHOICE type");
86 if (type.checkTag(type.id)) {
87 if (type.checkTag(type.constrId)) {
88 // the base encoding can be primitive ot constructed
90 taggingType = TAGGING_STRING;
92 // if the base encoding is primitive use primitive encoding
93 taggingType = TAGGING_PRIMITIVE;
96 // if the base encoding is constructed use constructed encoding
97 taggingType = TAGGING_CONSTRUCTED;
110 public final boolean checkTag(int identifier) {
111 switch (taggingType) {
112 case TAGGING_PRIMITIVE:
113 return id == identifier;
114 case TAGGING_CONSTRUCTED:
115 return constrId == identifier;
116 default: // TAGGING_STRING
117 return id == identifier || constrId == identifier;
124 public Object decode(BerInputStream in) throws IOException {
125 if (!checkTag(in.tag)) {
126 // FIXME need look for tagging type
127 throw new ASN1Exception("ASN.1 implicitly tagged type expected at " +
128 "[" + in.tagOffset + "]. Expected tag: " + Integer.toHexString(id) + ", " +
129 "but got " + Integer.toHexString(in.tag));
132 // substitute indentifier for further decoding
136 in.tag = type.constrId;
138 in.content = type.decode(in);
143 return getDecodedObject(in);
152 public void encodeASN(BerOutputStream out) {
153 //FIXME need another way for specifying identifier to be encoded
154 if (taggingType == TAGGING_CONSTRUCTED) {
155 out.encodeTag(constrId);
162 public void encodeContent(BerOutputStream out) {
163 type.encodeContent(out);
166 public void setEncodingContent(BerOutputStream out) {
167 type.setEncodingContent(out);