OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / harmony / security / asn1 / ASN1Implicit.java
1 /*
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /**
19 * @author Vladimir N. Molotkov, Stepan M. Mishura
20 * @version $Revision$
21 */
22
23 package org.apache.harmony.security.asn1;
24
25 import java.io.IOException;
26
27
28 /**
29  * Implicitly tagged ASN.1 type.
30  *
31  * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
32  */
33 public class ASN1Implicit extends ASN1Type {
34
35     // primitive type of tagging
36     private static final int TAGGING_PRIMITIVE = 0;
37
38     // constructed type of tagging
39     private static final int TAGGING_CONSTRUCTED = 1;
40
41     // string type of tagging
42     private static final int TAGGING_STRING = 2;
43
44     // tagged ASN.1 type
45     private final ASN1Type type;
46
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;
52
53     /**
54      * Constructs implicitly tagged ASN.1 type
55      * with context-specific tag class and specified tag number.
56      *
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
60      */
61     public ASN1Implicit(int tagNumber, ASN1Type type) {
62         this(CLASS_CONTEXTSPECIFIC, tagNumber, type);
63     }
64
65     /**
66      * Constructs implicitly tagged ASN.1 type
67      *
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
72      */
73     public ASN1Implicit(int tagClass, int tagNumber, ASN1Type type) {
74         super(tagClass, tagNumber);
75
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");
82         }
83
84         this.type = type;
85
86         if (type.checkTag(type.id)) {
87             if (type.checkTag(type.constrId)) {
88                 // the base encoding can be primitive ot constructed
89                 // use both encodings
90                 taggingType = TAGGING_STRING;
91             } else {
92                 // if the base encoding is primitive use primitive encoding
93                 taggingType = TAGGING_PRIMITIVE;
94             }
95         } else {
96             // if the base encoding is constructed use constructed encoding
97             taggingType = TAGGING_CONSTRUCTED;
98         }
99     }
100
101     //
102     //
103     // Decode
104     //
105     //
106
107     /**
108      * TODO
109      */
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;
118         }
119     }
120
121     /**
122      * TODO
123      */
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));
130         }
131
132         // substitute indentifier for further decoding
133         if (id == in.tag) {
134             in.tag = type.id;
135         } else {
136             in.tag = type.constrId;
137         }
138         in.content = type.decode(in);
139
140         if (in.isVerify) {
141             return null;
142         }
143         return getDecodedObject(in);
144     }
145
146     //
147     //
148     // Encode
149     //
150     //
151
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);
156         } else {
157             out.encodeTag(id);
158         }
159         encodeContent(out);
160     }
161
162     public void encodeContent(BerOutputStream out) {
163         type.encodeContent(out);
164     }
165
166     public void setEncodingContent(BerOutputStream out) {
167         type.setEncodingContent(out);
168     }
169 }