View Javadoc
1   /*
2    * Copyright (c) 1997, 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.io.OutputStream;
30  import java.math.BigInteger;
31  import java.util.Enumeration;
32  
33  import sun.security.util.*;
34  
35  /**
36   * Represent the CRL Number Extension.
37   *
38   * <p>This extension, if present, conveys a monotonically increasing
39   * sequence number for each CRL issued by a given CA through a specific
40   * CA X.500 Directory entry or CRL distribution point. This extension
41   * allows users to easily determine when a particular CRL supersedes
42   * another CRL.
43   *
44   * @author Hemma Prafullchandra
45   * @see Extension
46   * @see CertAttrSet
47   */
48  public class CRLNumberExtension extends Extension
49  implements CertAttrSet<String> {
50  
51      /**
52       * Attribute name.
53       */
54      public static final String NAME = "CRLNumber";
55      public static final String NUMBER = "value";
56  
57      private static final String LABEL = "CRL Number";
58  
59      private BigInteger crlNumber = null;
60      private String extensionName;
61      private String extensionLabel;
62  
63      // Encode this extension value
64      private void encodeThis() throws IOException {
65          if (crlNumber == null) {
66              this.extensionValue = null;
67              return;
68          }
69          DerOutputStream os = new DerOutputStream();
70          os.putInteger(this.crlNumber);
71          this.extensionValue = os.toByteArray();
72      }
73  
74      /**
75       * Create a CRLNumberExtension with the integer value .
76       * The criticality is set to false.
77       *
78       * @param crlNum the value to be set for the extension.
79       */
80      public CRLNumberExtension(int crlNum) throws IOException {
81          this(PKIXExtensions.CRLNumber_Id, false, BigInteger.valueOf(crlNum),
82          NAME, LABEL);
83      }
84  
85      /**
86       * Create a CRLNumberExtension with the BigInteger value .
87       * The criticality is set to false.
88       *
89       * @param crlNum the value to be set for the extension.
90       */
91      public CRLNumberExtension(BigInteger crlNum) throws IOException {
92          this(PKIXExtensions.CRLNumber_Id, false, crlNum, NAME, LABEL);
93      }
94  
95      /**
96       * Creates the extension (also called by the subclass).
97       */
98      protected CRLNumberExtension(ObjectIdentifier extensionId,
99          boolean isCritical, BigInteger crlNum, String extensionName,
100         String extensionLabel) throws IOException {
101 
102         this.extensionId = extensionId;
103         this.critical = isCritical;
104         this.crlNumber = crlNum;
105         this.extensionName = extensionName;
106         this.extensionLabel = extensionLabel;
107         encodeThis();
108     }
109 
110     /**
111      * Create the extension from the passed DER encoded value of the same.
112      *
113      * @param critical true if the extension is to be treated as critical.
114      * @param value an array of DER encoded bytes of the actual value.
115      * @exception ClassCastException if value is not an array of bytes
116      * @exception IOException on error.
117      */
118     public CRLNumberExtension(Boolean critical, Object value)
119     throws IOException {
120         this(PKIXExtensions.CRLNumber_Id, critical, value, NAME, LABEL);
121     }
122 
123     /**
124      * Creates the extension (also called by the subclass).
125      */
126     protected CRLNumberExtension(ObjectIdentifier extensionId,
127         Boolean critical, Object value, String extensionName,
128         String extensionLabel) throws IOException {
129 
130         this.extensionId = extensionId;
131         this.critical = critical.booleanValue();
132         this.extensionValue = (byte[]) value;
133         DerValue val = new DerValue(this.extensionValue);
134         this.crlNumber = val.getBigInteger();
135         this.extensionName = extensionName;
136         this.extensionLabel = extensionLabel;
137     }
138 
139     /**
140      * Set the attribute value.
141      */
142     public void set(String name, Object obj) throws IOException {
143         if (name.equalsIgnoreCase(NUMBER)) {
144             if (!(obj instanceof BigInteger)) {
145                 throw new IOException("Attribute must be of type BigInteger.");
146             }
147             crlNumber = (BigInteger)obj;
148         } else {
149           throw new IOException("Attribute name not recognized by"
150                                 + " CertAttrSet:" + extensionName + ".");
151         }
152         encodeThis();
153     }
154 
155     /**
156      * Get the attribute value.
157      */
158     public BigInteger get(String name) throws IOException {
159         if (name.equalsIgnoreCase(NUMBER)) {
160             if (crlNumber == null) return null;
161             else return crlNumber;
162         } else {
163           throw new IOException("Attribute name not recognized by"
164                                 + " CertAttrSet:" + extensionName + ".");
165         }
166     }
167 
168     /**
169      * Delete the attribute value.
170      */
171     public void delete(String name) throws IOException {
172         if (name.equalsIgnoreCase(NUMBER)) {
173             crlNumber = null;
174         } else {
175           throw new IOException("Attribute name not recognized by"
176                                 + " CertAttrSet:" + extensionName + ".");
177         }
178         encodeThis();
179     }
180 
181     /**
182      * Returns a printable representation of the CRLNumberExtension.
183      */
184     public String toString() {
185         String s = super.toString() + extensionLabel + ": " +
186                    ((crlNumber == null) ? "" : Debug.toHexString(crlNumber))
187                    + "\n";
188         return (s);
189     }
190 
191     /**
192      * Write the extension to the DerOutputStream.
193      *
194      * @param out the DerOutputStream to write the extension to.
195      * @exception IOException on encoding errors.
196      */
197     public void encode(OutputStream out) throws IOException {
198        DerOutputStream  tmp = new DerOutputStream();
199         encode(out, PKIXExtensions.CRLNumber_Id, true);
200     }
201 
202     /**
203      * Write the extension to the DerOutputStream.
204      * (Also called by the subclass)
205      */
206     protected void encode(OutputStream out, ObjectIdentifier extensionId,
207         boolean isCritical) throws IOException {
208 
209        DerOutputStream  tmp = new DerOutputStream();
210 
211        if (this.extensionValue == null) {
212            this.extensionId = extensionId;
213            this.critical = isCritical;
214            encodeThis();
215        }
216        super.encode(tmp);
217        out.write(tmp.toByteArray());
218     }
219 
220     /**
221      * Return an enumeration of names of attributes existing within this
222      * attribute.
223      */
224     public Enumeration<String> getElements() {
225         AttributeNameEnumeration elements = new AttributeNameEnumeration();
226         elements.addElement(NUMBER);
227         return (elements.elements());
228     }
229 
230     /**
231      * Return the name of this attribute.
232      */
233     public String getName() {
234         return (extensionName);
235     }
236 }