Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 2000, 2011, 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 
     26 package sun.security.x509;
     27 
     28 import java.io.IOException;
     29 import java.security.cert.PolicyQualifierInfo;
     30 import java.util.Collections;
     31 import java.util.Enumeration;
     32 import java.util.Iterator;
     33 import java.util.LinkedHashSet;
     34 import java.util.Set;
     35 
     36 import sun.security.util.DerValue;
     37 import sun.security.util.DerOutputStream;
     38 /**
     39  * PolicyInformation is the class that contains a specific certificate policy
     40  * that is part of the CertificatePoliciesExtension. A
     41  * CertificatePolicyExtension value consists of a vector of these objects.
     42  * <p>
     43  * The ASN.1 syntax for PolicyInformation (IMPLICIT tagging is defined in the
     44  * module definition):
     45  * <pre>
     46  *
     47  * PolicyInformation ::= SEQUENCE {
     48  *      policyIdentifier   CertPolicyId,
     49  *      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
     50  *                              PolicyQualifierInfo OPTIONAL }
     51  *
     52  * CertPolicyId ::= OBJECT IDENTIFIER
     53  *
     54  * PolicyQualifierInfo ::= SEQUENCE {
     55  *      policyQualifierId  PolicyQualifierId,
     56  *      qualifier          ANY DEFINED BY policyQualifierId }
     57  * </pre>
     58  *
     59  * @author Sean Mullan
     60  * @author Anne Anderson
     61  * @since       1.4
     62  */
     63 public class PolicyInformation {
     64 
     65     // Attribute names
     66     public static final String NAME       = "PolicyInformation";
     67     public static final String ID         = "id";
     68     public static final String QUALIFIERS = "qualifiers";
     69 
     70     /* The policy OID */
     71     private CertificatePolicyId policyIdentifier;
     72 
     73     /* A Set of java.security.cert.PolicyQualifierInfo objects */
     74     private Set<PolicyQualifierInfo> policyQualifiers;
     75 
     76     /**
     77      * Create an instance of PolicyInformation
     78      *
     79      * @param policyIdentifier the policyIdentifier as a
     80      *          CertificatePolicyId
     81      * @param policyQualifiers a Set of PolicyQualifierInfo objects.
     82      *          Must not be NULL. Specify an empty Set for no qualifiers.
     83      * @exception IOException on decoding errors.
     84      */
     85     public PolicyInformation(CertificatePolicyId policyIdentifier,
     86             Set<PolicyQualifierInfo> policyQualifiers) throws IOException {
     87         if (policyQualifiers == null) {
     88             throw new NullPointerException("policyQualifiers is null");
     89         }
     90         this.policyQualifiers =
     91             new LinkedHashSet<PolicyQualifierInfo>(policyQualifiers);
     92         this.policyIdentifier = policyIdentifier;
     93     }
     94 
     95     /**
     96      * Create an instance of PolicyInformation, decoding from
     97      * the passed DerValue.
     98      *
     99      * @param val the DerValue to construct the PolicyInformation from.
    100      * @exception IOException on decoding errors.
    101      */
    102     public PolicyInformation(DerValue val) throws IOException {
    103         if (val.tag != DerValue.tag_Sequence) {
    104             throw new IOException("Invalid encoding of PolicyInformation");
    105         }
    106         policyIdentifier = new CertificatePolicyId(val.data.getDerValue());
    107         if (val.data.available() != 0) {
    108             policyQualifiers = new LinkedHashSet<PolicyQualifierInfo>();
    109             DerValue opt = val.data.getDerValue();
    110             if (opt.tag != DerValue.tag_Sequence)
    111                 throw new IOException("Invalid encoding of PolicyInformation");
    112             if (opt.data.available() == 0)
    113                 throw new IOException("No data available in policyQualifiers");
    114             while (opt.data.available() != 0)
    115                 policyQualifiers.add(new PolicyQualifierInfo
    116                         (opt.data.getDerValue().toByteArray()));
    117         } else {
    118             policyQualifiers = Collections.emptySet();
    119         }
    120     }
    121 
    122     /**
    123      * Compare this PolicyInformation with another object for equality
    124      *
    125      * @param other object to be compared with this
    126      * @return true iff the PolicyInformation objects match
    127      */
    128     public boolean equals(Object other) {
    129         if (!(other instanceof PolicyInformation))
    130             return false;
    131         PolicyInformation piOther = (PolicyInformation)other;
    132 
    133         if (!policyIdentifier.equals(piOther.getPolicyIdentifier()))
    134             return false;
    135 
    136         return policyQualifiers.equals(piOther.getPolicyQualifiers());
    137     }
    138 
    139     /**
    140      * Returns the hash code for this PolicyInformation.
    141      *
    142      * @return a hash code value.
    143      */
    144     public int hashCode() {
    145         int myhash = 37 + policyIdentifier.hashCode();
    146         myhash = 37 * myhash + policyQualifiers.hashCode();
    147         return myhash;
    148     }
    149 
    150     /**
    151      * Return the policyIdentifier value
    152      *
    153      * @return The CertificatePolicyId object containing
    154      *     the policyIdentifier (not a copy).
    155      */
    156     public CertificatePolicyId getPolicyIdentifier() {
    157         return policyIdentifier;
    158     }
    159 
    160     /**
    161      * Return the policyQualifiers value
    162      *
    163      * @return a Set of PolicyQualifierInfo objects associated
    164      *    with this certificate policy (not a copy).
    165      *    Returns an empty Set if there are no qualifiers.
    166      *    Never returns null.
    167      */
    168     public Set<PolicyQualifierInfo> getPolicyQualifiers() {
    169         return policyQualifiers;
    170     }
    171 
    172     /**
    173      * Get the attribute value.
    174      */
    175     public Object get(String name) throws IOException {
    176         if (name.equalsIgnoreCase(ID)) {
    177             return policyIdentifier;
    178         } else if (name.equalsIgnoreCase(QUALIFIERS)) {
    179             return policyQualifiers;
    180         } else {
    181             throw new IOException("Attribute name [" + name +
    182                 "] not recognized by PolicyInformation.");
    183         }
    184     }
    185 
    186     /**
    187      * Set the attribute value.
    188      */
    189     @SuppressWarnings("unchecked") // Checked with instanceof
    190     public void set(String name, Object obj) throws IOException {
    191         if (name.equalsIgnoreCase(ID)) {
    192             if (obj instanceof CertificatePolicyId)
    193                 policyIdentifier = (CertificatePolicyId)obj;
    194             else
    195                 throw new IOException("Attribute value must be instance " +
    196                     "of CertificatePolicyId.");
    197         } else if (name.equalsIgnoreCase(QUALIFIERS)) {
    198             if (policyIdentifier == null) {
    199                 throw new IOException("Attribute must have a " +
    200                     "CertificatePolicyIdentifier value before " +
    201                     "PolicyQualifierInfo can be set.");
    202             }
    203             if (obj instanceof Set) {
    204                 Iterator<?> i = ((Set<?>)obj).iterator();
    205                 while (i.hasNext()) {
    206                     Object obj1 = i.next();
    207                     if (!(obj1 instanceof PolicyQualifierInfo)) {
    208                         throw new IOException("Attribute value must be a" +
    209                                     "Set of PolicyQualifierInfo objects.");
    210                     }
    211                 }
    212                 policyQualifiers = (Set<PolicyQualifierInfo>) obj;
    213             } else {
    214                 throw new IOException("Attribute value must be of type Set.");
    215             }
    216         } else {
    217             throw new IOException("Attribute name [" + name +
    218                 "] not recognized by PolicyInformation");
    219         }
    220     }
    221 
    222     /**
    223      * Delete the attribute value.
    224      */
    225     public void delete(String name) throws IOException {
    226         if (name.equalsIgnoreCase(QUALIFIERS)) {
    227             policyQualifiers = Collections.emptySet();
    228         } else if (name.equalsIgnoreCase(ID)) {
    229             throw new IOException("Attribute ID may not be deleted from " +
    230                 "PolicyInformation.");
    231         } else {
    232             //ID may not be deleted
    233             throw new IOException("Attribute name [" + name +
    234                 "] not recognized by PolicyInformation.");
    235         }
    236     }
    237 
    238     /**
    239      * Return an enumeration of names of attributes existing within this
    240      * attribute.
    241      */
    242     public Enumeration<String> getElements() {
    243         AttributeNameEnumeration elements = new AttributeNameEnumeration();
    244         elements.addElement(ID);
    245         elements.addElement(QUALIFIERS);
    246 
    247         return elements.elements();
    248     }
    249 
    250     /**
    251      * Return the name of this attribute.
    252      */
    253     public String getName() {
    254         return NAME;
    255     }
    256 
    257     /**
    258      * Return a printable representation of the PolicyInformation.
    259      */
    260     public String toString() {
    261         StringBuilder s = new StringBuilder("  [" + policyIdentifier.toString());
    262         s.append(policyQualifiers + "  ]\n");
    263         return s.toString();
    264     }
    265 
    266     /**
    267      * Write the PolicyInformation to the DerOutputStream.
    268      *
    269      * @param out the DerOutputStream to write the extension to.
    270      * @exception IOException on encoding errors.
    271      */
    272     public void encode(DerOutputStream out) throws IOException {
    273         DerOutputStream tmp = new DerOutputStream();
    274         policyIdentifier.encode(tmp);
    275         if (!policyQualifiers.isEmpty()) {
    276             DerOutputStream tmp2 = new DerOutputStream();
    277             for (PolicyQualifierInfo pq : policyQualifiers) {
    278                 tmp2.write(pq.getEncoded());
    279             }
    280             tmp.write(DerValue.tag_Sequence, tmp2);
    281         }
    282         out.write(DerValue.tag_Sequence, tmp);
    283     }
    284 }
    285