001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vladimir N. Molotkov, Stepan M. Mishura
020: * @version $Revision$
021: */package org.apache.harmony.security.asn1;
022:
023: /**
024: * Encodes ASN.1 types with DER (X.690)
025: *
026: * @see http://asn1.elibel.tm.fr/en/standards/index.htm
027: */
028:
029: public final class DerOutputStream extends BerOutputStream {
030:
031: public DerOutputStream(ASN1Type asn1, Object object) {
032: super ();
033:
034: content = object;
035:
036: index = -1;
037: asn1.setEncodingContent(this );
038:
039: encoded = new byte[asn1.getEncodedLength(this )];
040:
041: index = 0;
042: asn1.encodeASN(this );
043: }
044:
045: public void encodeChoice(ASN1Choice choice) {
046:
047: ASN1Type type = (ASN1Type) val[index][0];
048:
049: content = val[index][1];
050:
051: index++;
052:
053: type.encodeASN(this );
054: }
055:
056: public void encodeExplicit(ASN1Explicit explicit) {
057:
058: content = val[index][0];
059: length = len[index][0];
060:
061: index++;
062:
063: explicit.type.encodeASN(this );
064: }
065:
066: public void encodeSequence(ASN1Sequence sequence) {
067:
068: ASN1Type[] type = sequence.type;
069:
070: Object[] values = val[index];
071: int[] compLens = len[index];
072:
073: index++;
074: for (int i = 0; i < type.length; i++) {
075:
076: if (values[i] == null) {
077: continue;
078: }
079:
080: content = values[i];
081: length = compLens[i];
082:
083: type[i].encodeASN(this );
084: }
085: }
086:
087: public void encodeSequenceOf(ASN1SequenceOf sequenceOf) {
088: encodeValueCollection(sequenceOf);
089: }
090:
091: public void encodeSetOf(ASN1SetOf setOf) {
092: encodeValueCollection(setOf);
093: }
094:
095: private final void encodeValueCollection(
096: ASN1ValueCollection collection) {
097:
098: Object[] values = val[index];
099: int[] compLens = len[index];
100:
101: index++;
102: for (int i = 0; i < values.length; i++) {
103:
104: content = values[i];
105: length = compLens[i];
106:
107: collection.type.encodeASN(this );
108: }
109: }
110:
111: /*
112: * DATA
113: */
114:
115: private final static int initSize = 32;
116:
117: private int index;
118:
119: private int[][] len = new int[initSize][];
120:
121: private Object[][] val = new Object[initSize][];
122:
123: private void push(int[] lengths, Object[] values) {
124:
125: index++;
126: if (index == val.length) {
127:
128: int[][] newLen = new int[val.length * 2][];
129: System.arraycopy(len, 0, newLen, 0, val.length);
130: len = newLen;
131:
132: Object[][] newVal = new Object[val.length * 2][];
133: System.arraycopy(val, 0, newVal, 0, val.length);
134: val = newVal;
135: }
136: len[index] = lengths;
137: val[index] = values;
138: }
139:
140: /*
141: * LENGTH
142: */
143:
144: public void getChoiceLength(ASN1Choice choice) {
145:
146: int i = choice.getIndex(content);
147: content = choice.getObjectToEncode(content);
148:
149: Object[] values = new Object[] { choice.type[i], content };
150:
151: push(null, values);
152:
153: choice.type[i].setEncodingContent(this );
154:
155: // in case if we get content bytes while getting its length
156: // FIXME what about remove it: need redesign
157: values[1] = content;
158: }
159:
160: public void getExplicitLength(ASN1Explicit explicit) {
161:
162: Object[] values = new Object[1];
163: int[] compLens = new int[1];
164:
165: values[0] = content;
166:
167: push(compLens, values);
168:
169: explicit.type.setEncodingContent(this );
170:
171: // in case if we get content bytes while getting its length
172: // FIXME what about remove it: need redesign
173: values[0] = content;
174: compLens[0] = length;
175:
176: length = explicit.type.getEncodedLength(this );
177: }
178:
179: public void getSequenceLength(ASN1Sequence sequence) {
180:
181: ASN1Type[] type = sequence.type;
182:
183: Object[] values = new Object[type.length];
184: int[] compLens = new int[type.length];
185:
186: sequence.getValues(content, values);
187:
188: push(compLens, values);
189:
190: int seqLen = 0;
191: for (int i = 0; i < type.length; i++) {
192: // check optional types
193: if (values[i] == null) {
194: if (sequence.OPTIONAL[i]) {
195: continue;
196: } else {
197: throw new RuntimeException();//FIXME type & message
198: }
199: }
200:
201: if (sequence.DEFAULT[i] != null
202: && sequence.DEFAULT[i].equals(values[i])) {
203: values[i] = null;
204: continue;
205: }
206:
207: content = values[i];
208:
209: type[i].setEncodingContent(this );
210:
211: compLens[i] = length;
212:
213: // in case if we get content bytes while getting its length
214: // FIXME what about remove it: need redesign
215: values[i] = content;
216:
217: seqLen += type[i].getEncodedLength(this );
218: }
219: length = seqLen;
220: }
221:
222: public void getSequenceOfLength(ASN1SequenceOf sequence) {
223: getValueOfLength(sequence);
224: }
225:
226: public void getSetOfLength(ASN1SetOf setOf) {
227: getValueOfLength(setOf);
228: }
229:
230: private void getValueOfLength(ASN1ValueCollection collection) {
231:
232: //FIXME what about another way?
233: Object[] cv = collection.getValues(content).toArray();
234:
235: Object[] values = new Object[cv.length];
236: int[] compLens = new int[values.length];
237:
238: push(compLens, values);
239: int seqLen = 0;
240: for (int i = 0; i < values.length; i++) {
241:
242: content = cv[i];
243:
244: collection.type.setEncodingContent(this );
245:
246: compLens[i] = length;
247:
248: // in case if we get content bytes while getting its length
249: // FIXME what about remove it: need redesign
250: values[i] = content;
251:
252: seqLen += collection.type.getEncodedLength(this);
253: }
254: length = seqLen;
255: }
256: }
|