1/*
2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.security.x509;
27
28import java.io.IOException;
29import sun.security.util.*;
30
31/**
32 * This class defines the EDIPartyName of the GeneralName choice.
33 * The ASN.1 syntax for this is:
34 * <pre>
35 * EDIPartyName ::= SEQUENCE {
36 *     nameAssigner  [0]  DirectoryString OPTIONAL,
37 *     partyName     [1]  DirectoryString }
38 * </pre>
39 *
40 * @author Hemma Prafullchandra
41 * @see GeneralName
42 * @see GeneralNames
43 * @see GeneralNameInterface
44 */
45public class EDIPartyName implements GeneralNameInterface {
46
47    // Private data members
48    private static final byte TAG_ASSIGNER = 0;
49    private static final byte TAG_PARTYNAME = 1;
50
51    private String assigner = null;
52    private String party = null;
53
54    private int myhash = -1;
55
56    /**
57     * Create the EDIPartyName object from the specified names.
58     *
59     * @param assignerName the name of the assigner
60     * @param partyName the name of the EDI party.
61     */
62    public EDIPartyName(String assignerName, String partyName) {
63        this.assigner = assignerName;
64        this.party = partyName;
65    }
66
67    /**
68     * Create the EDIPartyName object from the specified name.
69     *
70     * @param partyName the name of the EDI party.
71     */
72    public EDIPartyName(String partyName) {
73        this.party = partyName;
74    }
75
76    /**
77     * Create the EDIPartyName object from the passed encoded Der value.
78     *
79     * @param derValue the encoded DER EDIPartyName.
80     * @exception IOException on error.
81     */
82    public EDIPartyName(DerValue derValue) throws IOException {
83        DerInputStream in = new DerInputStream(derValue.toByteArray());
84        DerValue[] seq = in.getSequence(2);
85
86        int len = seq.length;
87        if (len < 1 || len > 2)
88            throw new IOException("Invalid encoding of EDIPartyName");
89
90        for (int i = 0; i < len; i++) {
91            DerValue opt = seq[i];
92            if (opt.isContextSpecific(TAG_ASSIGNER) &&
93                !opt.isConstructed()) {
94                if (assigner != null)
95                    throw new IOException("Duplicate nameAssigner found in"
96                                          + " EDIPartyName");
97                opt = opt.data.getDerValue();
98                assigner = opt.getAsString();
99            }
100            if (opt.isContextSpecific(TAG_PARTYNAME) &&
101                !opt.isConstructed()) {
102                if (party != null)
103                    throw new IOException("Duplicate partyName found in"
104                                          + " EDIPartyName");
105                opt = opt.data.getDerValue();
106                party = opt.getAsString();
107            }
108        }
109    }
110
111    /**
112     * Return the type of the GeneralName.
113     */
114    public int getType() {
115        return (GeneralNameInterface.NAME_EDI);
116    }
117
118    /**
119     * Encode the EDI party name into the DerOutputStream.
120     *
121     * @param out the DER stream to encode the EDIPartyName to.
122     * @exception IOException on encoding errors.
123     */
124    public void encode(DerOutputStream out) throws IOException {
125        DerOutputStream tagged = new DerOutputStream();
126        DerOutputStream tmp = new DerOutputStream();
127
128        if (assigner != null) {
129            DerOutputStream tmp2 = new DerOutputStream();
130            // XXX - shd check is chars fit into PrintableString
131            tmp2.putPrintableString(assigner);
132            tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
133                                 false, TAG_ASSIGNER), tmp2);
134        }
135        if (party == null)
136            throw  new IOException("Cannot have null partyName");
137
138        // XXX - shd check is chars fit into PrintableString
139        tmp.putPrintableString(party);
140        tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
141                                 false, TAG_PARTYNAME), tmp);
142
143        out.write(DerValue.tag_Sequence, tagged);
144    }
145
146    /**
147     * Return the assignerName
148     *
149     * @returns String assignerName
150     */
151    public String getAssignerName() {
152        return assigner;
153    }
154
155    /**
156     * Return the partyName
157     *
158     * @returns String partyName
159     */
160    public String getPartyName() {
161        return party;
162    }
163
164    /**
165     * Compare this EDIPartyName with another.  Does a byte-string
166     * comparison without regard to type of the partyName and
167     * the assignerName.
168     *
169     * @returns true if the two names match
170     */
171    public boolean equals(Object other) {
172        if (!(other instanceof EDIPartyName))
173            return false;
174        String otherAssigner = ((EDIPartyName)other).assigner;
175        if (this.assigner == null) {
176            if (otherAssigner != null)
177                return false;
178        } else {
179            if (!(this.assigner.equals(otherAssigner)))
180                return false;
181        }
182        String otherParty = ((EDIPartyName)other).party;
183        if (this.party == null) {
184            if (otherParty != null)
185                return false;
186        } else {
187            if (!(this.party.equals(otherParty)))
188                return false;
189        }
190        return true;
191    }
192
193    /**
194     * Returns the hash code value for this EDIPartyName.
195     *
196     * @return a hash code value.
197     */
198    public int hashCode() {
199        if (myhash == -1) {
200            myhash = 37 + (party == null ? 1 : party.hashCode());
201            if (assigner != null) {
202                myhash = 37 * myhash + assigner.hashCode();
203            }
204        }
205        return myhash;
206    }
207
208    /**
209     * Return the printable string.
210     */
211    public String toString() {
212        return ("EDIPartyName: " +
213                 ((assigner == null) ? "" :
214                   ("  nameAssigner = " + assigner + ","))
215                 + "  partyName = " + party);
216    }
217
218    /**
219     * Return constraint type:<ul>
220     *   <li>NAME_DIFF_TYPE = -1: input name is different type from name (i.e. does not constrain)
221     *   <li>NAME_MATCH = 0: input name matches name
222     *   <li>NAME_NARROWS = 1: input name narrows name
223     *   <li>NAME_WIDENS = 2: input name widens name
224     *   <li>NAME_SAME_TYPE = 3: input name does not match or narrow name, but is same type
225     * </ul>.  These results are used in checking NameConstraints during
226     * certification path verification.
227     *
228     * @param inputName to be checked for being constrained
229     * @returns constraint type above
230     * @throws UnsupportedOperationException if name is same type, but comparison operations are
231     *          not supported for this name type.
232     */
233    public int constrains(GeneralNameInterface inputName) throws UnsupportedOperationException {
234        int constraintType;
235        if (inputName == null)
236            constraintType = NAME_DIFF_TYPE;
237        else if (inputName.getType() != NAME_EDI)
238            constraintType = NAME_DIFF_TYPE;
239        else {
240            throw new UnsupportedOperationException("Narrowing, widening, and matching of names not supported for EDIPartyName");
241        }
242        return constraintType;
243    }
244
245    /**
246     * Return subtree depth of this name for purposes of determining
247     * NameConstraints minimum and maximum bounds and for calculating
248     * path lengths in name subtrees.
249     *
250     * @returns distance of name from root
251     * @throws UnsupportedOperationException if not supported for this name type
252     */
253    public int subtreeDepth() throws UnsupportedOperationException {
254        throw new UnsupportedOperationException("subtreeDepth() not supported for EDIPartyName");
255    }
256
257}
258