blob: b4f3e291307f7222227726662198eddea9535688 [file] [log] [blame]
slowr60d4d102017-08-16 18:33:58 -07001/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Dimitrios Mavrommatis96b255a2017-12-06 13:09:25 -08004package org.onosproject.xran.asn1lib.ber.types;
slowr60d4d102017-08-16 18:33:58 -07005
6import com.fasterxml.jackson.annotation.JsonIgnore;
7import com.fasterxml.jackson.annotation.JsonValue;
Dimitrios Mavrommatis96b255a2017-12-06 13:09:25 -08008import org.onosproject.xran.asn1lib.ber.BerByteArrayOutputStream;
9import org.onosproject.xran.asn1lib.ber.BerLength;
10import org.onosproject.xran.asn1lib.ber.BerTag;
11import org.onosproject.xran.asn1lib.ber.internal.Util;
slowr60d4d102017-08-16 18:33:58 -070012
13import java.io.IOException;
14import java.io.InputStream;
15import java.io.Serializable;
16import java.util.ArrayList;
17import java.util.List;
18
19public class BerObjectIdentifier implements Serializable {
20
21 public final static BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.OBJECT_IDENTIFIER_TAG);
22 private static final long serialVersionUID = 1L;
Dimitrios Mavrommatis96b255a2017-12-06 13:09:25 -080023
24 @JsonIgnore public byte[] code = null;
slowr60d4d102017-08-16 18:33:58 -070025
26 public int[] value;
27
28 public BerObjectIdentifier() {
29 }
30
31 public BerObjectIdentifier(byte[] code) {
32 this.code = code;
33 }
34
35 public BerObjectIdentifier(int[] value) {
36 if ((value.length < 2) || ((value[0] == 0 || value[0] == 1) && (value[1] > 39)) || value[0] > 2) {
37 throw new IllegalArgumentException("invalid object identifier components");
38 }
39 for (int objectIdentifierComponent : value) {
40 if (objectIdentifierComponent < 0) {
41 throw new IllegalArgumentException("invalid object identifier components");
42 }
43 }
44
45 this.value = value;
46
47 }
48
49 public int encode(BerByteArrayOutputStream os) throws IOException {
50 return encode(os, true);
51 }
52
53 public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
54
55 if (code != null) {
56 for (int i = code.length - 1; i >= 0; i--) {
57 os.write(code[i]);
58 }
59 if (withTag) {
60 return tag.encode(os) + code.length;
61 }
62 return code.length;
63 }
64
65 int firstSubidentifier = 40 * value[0] + value[1];
66
67 int subidentifier;
68
69 int codeLength = 0;
70
71 for (int i = (value.length - 1); i > 0; i--) {
72
73 if (i == 1) {
74 subidentifier = firstSubidentifier;
75 } else {
76 subidentifier = value[i];
77 }
78
79 // get length of subidentifier
80 int subIDLength = 1;
81 while (subidentifier > (Math.pow(2, (7 * subIDLength)) - 1)) {
82 subIDLength++;
83 }
84
85 os.write(subidentifier & 0x7f);
86
87 for (int j = 1; j <= (subIDLength - 1); j++) {
88 os.write(((subidentifier >> (7 * j)) & 0xff) | 0x80);
89 }
90
91 codeLength += subIDLength;
92 }
93
94 codeLength += BerLength.encodeLength(os, codeLength);
95
96 if (withTag) {
97 codeLength += tag.encode(os);
98 }
99
100 return codeLength;
101 }
102
103 public int decode(InputStream is) throws IOException {
104 return decode(is, true);
105 }
106
107 public int decode(InputStream is, boolean withTag) throws IOException {
108
109 int codeLength = 0;
110
111 if (withTag) {
112 codeLength += tag.decodeAndCheck(is);
113 }
114
115 BerLength length = new BerLength();
116 codeLength += length.decode(is);
117
118 if (length.val == 0) {
119 value = new int[0];
120 return codeLength;
121 }
122
123 byte[] byteCode = new byte[length.val];
124 Util.readFully(is, byteCode);
125
126 codeLength += length.val;
127
128 List<Integer> objectIdentifierComponentsList = new ArrayList<>();
129
130 int subIDEndIndex = 0;
131 while ((byteCode[subIDEndIndex] & 0x80) == 0x80) {
132 if (subIDEndIndex >= (length.val - 1)) {
133 throw new IOException("Invalid Object Identifier");
134 }
135 subIDEndIndex++;
136 }
137
138 int subidentifier = 0;
139 for (int i = 0; i <= subIDEndIndex; i++) {
140 subidentifier |= (byteCode[i] << ((subIDEndIndex - i) * 7));
141 }
142
143 if (subidentifier < 40) {
144 objectIdentifierComponentsList.add(0);
145 objectIdentifierComponentsList.add(subidentifier);
146 } else if (subidentifier < 80) {
147 objectIdentifierComponentsList.add(1);
148 objectIdentifierComponentsList.add(subidentifier - 40);
149 } else {
150 objectIdentifierComponentsList.add(2);
151 objectIdentifierComponentsList.add(subidentifier - 80);
152 }
153
154 subIDEndIndex++;
155
156 while (subIDEndIndex < length.val) {
157 int subIDStartIndex = subIDEndIndex;
158
159 while ((byteCode[subIDEndIndex] & 0x80) == 0x80) {
160 if (subIDEndIndex == (length.val - 1)) {
161 throw new IOException("Invalid Object Identifier");
162 }
163 subIDEndIndex++;
164 }
165 subidentifier = 0;
166 for (int j = subIDStartIndex; j <= subIDEndIndex; j++) {
167 subidentifier |= ((byteCode[j] & 0x7f) << ((subIDEndIndex - j) * 7));
168 }
169 objectIdentifierComponentsList.add(subidentifier);
170 subIDEndIndex++;
171 }
172
173 value = new int[objectIdentifierComponentsList.size()];
174 for (int i = 0; i < objectIdentifierComponentsList.size(); i++) {
175 value[i] = objectIdentifierComponentsList.get(i);
176 }
177
178 return codeLength;
179
180 }
181
Dimitrios Mavrommatis96b255a2017-12-06 13:09:25 -0800182
slowr60d4d102017-08-16 18:33:58 -0700183 @Override
184 public String toString() {
185 if (value == null || value.length == 0) {
186 return "";
187 }
188
189 String objIDString = "";
190 objIDString += value[0];
191 for (int i = 1; i < value.length; i++) {
192 objIDString += "." + value[i];
193 }
194 return objIDString;
195 }
196
197 public BerObjectIdentifier append(int value) {
198 if (this.value == null) {
199 return new BerObjectIdentifier(new int[]{value});
200 }
201 int[] values = new int[this.value.length + 1];
202 for (int i = 0; i < this.value.length; ++i) {
203 values[i] = this.value[i];
204 }
205 values[values.length - 1] = value;
206 return new BerObjectIdentifier(values);
207 }
208
209}