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.util.ArrayList;
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/**
34 * The class encapsulates the ASN.1 DER encoding/decoding work
35 * with the GeneralNames structure which is a part of X.509 certificate
36 * (as specified in RFC 3280 -
37 *  Internet X.509 Public Key Infrastructure.
38 *  Certificate and Certificate Revocation List (CRL) Profile.
39 *  http://www.ietf.org/rfc/rfc3280.txt):
40 *
41 *
42 * <pre>
43 *   GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
44 * </pre>
45 *
46 * @see org.apache.harmony.security.x509.NameConstraints
47 * @see org.apache.harmony.security.x509.GeneralSubtree
48 */
49public final class GeneralNames {
50    /** the values of GeneralName */
51    private List<GeneralName> generalNames;
52    /** the ASN.1 encoded form of GeneralNames */
53    private byte[] encoding;
54
55    public GeneralNames() {
56        generalNames = new ArrayList<GeneralName>();
57    }
58
59    public GeneralNames(List<GeneralName> generalNames) {
60        this.generalNames = generalNames;
61    }
62
63    private GeneralNames(List<GeneralName> generalNames, byte[] encoding) {
64        this.generalNames = generalNames;
65        this.encoding = encoding;
66    }
67
68    /**
69     * Returns the list of values.
70     */
71    public List<GeneralName> getNames() {
72        if ((generalNames == null) || (generalNames.size() == 0)) {
73            return null;
74        }
75        return new ArrayList<GeneralName>(generalNames);
76    }
77
78    /**
79     * Returns the collection of pairs: (Integer (tag), Object (name value))*
80     */
81    public Collection<List<?>> getPairsList() {
82        Collection<List<?>> result = new ArrayList<List<?>>();
83        if (generalNames == null) {
84            return result;
85        }
86        for (GeneralName generalName : generalNames) {
87            /*
88             * If we have an error decoding one of the GeneralNames, we'll just
89             * omit it from the final list.
90             */
91            final List<Object> genNameList;
92            try {
93                genNameList = generalName.getAsList();
94            } catch (IllegalArgumentException ignored) {
95                continue;
96            }
97
98            result.add(genNameList);
99        }
100        return result;
101    }
102
103    public void addName(GeneralName name) {
104        encoding = null;
105        if (generalNames == null) {
106            generalNames = new ArrayList<GeneralName>();
107        }
108        generalNames.add(name);
109    }
110
111    /**
112     * Returns ASN.1 encoded form of this X.509 GeneralNames value.
113     */
114    public byte[] getEncoded() {
115        if (encoding == null) {
116            encoding = ASN1.encode(this);
117        }
118        return encoding;
119    }
120
121    public void dumpValue(StringBuilder sb, String prefix) {
122        if (generalNames == null) {
123            return;
124        }
125        for (GeneralName generalName : generalNames) {
126            sb.append(prefix);
127            sb.append(generalName);
128            sb.append('\n');
129        }
130    }
131
132    /**
133     * ASN.1 DER X.509 GeneralNames encoder/decoder class.
134     */
135    public static final ASN1Type ASN1 = new ASN1SequenceOf(GeneralName.ASN1) {
136        @Override public Object getDecodedObject(BerInputStream in) {
137            return new GeneralNames((List<GeneralName>) in.content, in.getEncoded());
138        }
139
140        @Override public Collection getValues(Object object) {
141            GeneralNames gns = (GeneralNames) object;
142            return gns.generalNames;
143        }
144    };
145}
146