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 Alexander Y. Kleymenov
20* @version $Revision$
21*/
22
23package org.apache.harmony.security.x509;
24
25import java.io.IOException;
26import java.util.Collection;
27import java.util.List;
28import org.apache.harmony.security.asn1.ASN1SequenceOf;
29import org.apache.harmony.security.asn1.ASN1Type;
30import org.apache.harmony.security.asn1.BerInputStream;
31
32/**
33 * The class encapsulates the ASN.1 DER encoding/decoding work
34 * with the CRL Distribution Points which is the part of X.509 Certificate
35 * (as specified in RFC 3280 -
36 *  Internet X.509 Public Key Infrastructure.
37 *  Certificate and Certificate Revocation List (CRL) Profile.
38 *  http://www.ietf.org/rfc/rfc3280.txt):
39 *
40 * <pre>
41 *  CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
42 *
43 *  DistributionPoint ::= SEQUENCE {
44 *        distributionPoint       [0]     DistributionPointName OPTIONAL,
45 *        reasons                 [1]     ReasonFlags OPTIONAL,
46 *        cRLIssuer               [2]     GeneralNames OPTIONAL
47 *  }
48 *
49 *  DistributionPointName ::= CHOICE {
50 *        fullName                [0]     GeneralNames,
51 *        nameRelativeToCRLIssuer [1]     RelativeDistinguishedName
52 *  }
53 *
54 *  ReasonFlags ::= BIT STRING {
55 *        unused                  (0),
56 *        keyCompromise           (1),
57 *        cACompromise            (2),
58 *        affiliationChanged      (3),
59 *        superseded              (4),
60 *        cessationOfOperation    (5),
61 *        certificateHold         (6),
62 *        privilegeWithdrawn      (7),
63 *        aACompromise            (8)
64 *  }
65 * </pre>
66 */
67public final class CRLDistributionPoints extends ExtensionValue {
68    private List<DistributionPoint> distributionPoints;
69    private byte[] encoding;
70
71    private CRLDistributionPoints(List<DistributionPoint> distributionPoints, byte[] encoding) {
72        if ((distributionPoints == null) || (distributionPoints.size() == 0)) {
73            throw new IllegalArgumentException("distributionPoints are empty");
74        }
75        this.distributionPoints = distributionPoints;
76        this.encoding = encoding;
77    }
78
79    @Override public byte[] getEncoded() {
80        if (encoding == null) {
81            encoding = ASN1.encode(this);
82        }
83        return encoding;
84    }
85
86    public static CRLDistributionPoints decode(byte[] encoding) throws IOException {
87        return (CRLDistributionPoints) ASN1.decode(encoding);
88    }
89
90    @Override public void dumpValue(StringBuilder sb, String prefix) {
91        sb.append(prefix).append("CRL Distribution Points: [\n");
92        int number = 0;
93        for (DistributionPoint distributionPoint : distributionPoints) {
94            sb.append(prefix).append("  [").append(++number).append("]\n");
95            distributionPoint.dumpValue(sb, prefix + "  ");
96        }
97        sb.append(prefix).append("]\n");
98    }
99
100    /**
101     * Custom X.509 decoder.
102     */
103    public static final ASN1Type ASN1 = new ASN1SequenceOf(DistributionPoint.ASN1) {
104        @Override public Object getDecodedObject(BerInputStream in) {
105            return new CRLDistributionPoints((List<DistributionPoint>) in.content, in.getEncoded());
106        }
107
108        @Override public Collection<?> getValues(Object object) {
109            CRLDistributionPoints dps = (CRLDistributionPoints) object;
110            return dps.distributionPoints;
111        }
112    };
113}
114