Home | History | Annotate | Download | only in x509
      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 
     26 package sun.security.x509;
     27 
     28 import java.io.*;
     29 
     30 import sun.security.util.*;
     31 
     32 /**
     33  * Represent the GeneralSubtree ASN.1 object, whose syntax is:
     34  * <pre>
     35  * GeneralSubtree ::= SEQUENCE {
     36  *    base             GeneralName,
     37  *    minimum  [0]     BaseDistance DEFAULT 0,
     38  *    maximum  [1]     BaseDistance OPTIONAL
     39  * }
     40  * BaseDistance ::= INTEGER (0..MAX)
     41  * </pre>
     42  * @author Amit Kapoor
     43  * @author Hemma Prafullchandra
     44  */
     45 public class GeneralSubtree {
     46     private static final byte TAG_MIN = 0;
     47     private static final byte TAG_MAX = 1;
     48     private static final int  MIN_DEFAULT = 0;
     49 
     50     private GeneralName name;
     51     private int         minimum = MIN_DEFAULT;
     52     private int         maximum = -1;
     53 
     54     private int myhash = -1;
     55 
     56     /**
     57      * The default constructor for the class.
     58      *
     59      * @params name the GeneralName
     60      * @params min the minimum BaseDistance
     61      * @params max the maximum BaseDistance
     62      */
     63     public GeneralSubtree(GeneralName name, int min, int max) {
     64         this.name = name;
     65         this.minimum = min;
     66         this.maximum = max;
     67     }
     68 
     69     /**
     70      * Create the object from its DER encoded form.
     71      *
     72      * @param val the DER encoded from of the same.
     73      */
     74     public GeneralSubtree(DerValue val) throws IOException {
     75         if (val.tag != DerValue.tag_Sequence) {
     76             throw new IOException("Invalid encoding for GeneralSubtree.");
     77         }
     78         name = new GeneralName(val.data.getDerValue(), true);
     79 
     80         // NB. this is always encoded with the IMPLICIT tag
     81         // The checks only make sense if we assume implicit tagging,
     82         // with explicit tagging the form is always constructed.
     83         while (val.data.available() != 0) {
     84             DerValue opt = val.data.getDerValue();
     85 
     86             if (opt.isContextSpecific(TAG_MIN) && !opt.isConstructed()) {
     87                 opt.resetTag(DerValue.tag_Integer);
     88                 minimum = opt.getInteger();
     89 
     90             } else if (opt.isContextSpecific(TAG_MAX) && !opt.isConstructed()) {
     91                 opt.resetTag(DerValue.tag_Integer);
     92                 maximum = opt.getInteger();
     93             } else
     94                 throw new IOException("Invalid encoding of GeneralSubtree.");
     95         }
     96     }
     97 
     98     /**
     99      * Return the GeneralName.
    100      *
    101      * @return the GeneralName
    102      */
    103     public GeneralName getName() {
    104         //XXXX May want to consider cloning this
    105         return name;
    106     }
    107 
    108     /**
    109      * Return the minimum BaseDistance.
    110      *
    111      * @return the minimum BaseDistance. Default is 0 if not set.
    112      */
    113     public int getMinimum() {
    114         return minimum;
    115     }
    116 
    117     /**
    118      * Return the maximum BaseDistance.
    119      *
    120      * @return the maximum BaseDistance, or -1 if not set.
    121      */
    122     public int getMaximum() {
    123         return maximum;
    124     }
    125 
    126     /**
    127      * Return a printable string of the GeneralSubtree.
    128      */
    129     public String toString() {
    130         String s = "\n   GeneralSubtree: [\n" +
    131             "    GeneralName: " + ((name == null) ? "" : name.toString()) +
    132             "\n    Minimum: " + minimum;
    133             if (maximum == -1) {
    134                 s += "\t    Maximum: undefined";
    135             } else
    136                 s += "\t    Maximum: " + maximum;
    137             s += "    ]\n";
    138         return (s);
    139     }
    140 
    141     /**
    142      * Compare this GeneralSubtree with another
    143      *
    144      * @param other GeneralSubtree to compare to this
    145      * @returns true if match
    146      */
    147     public boolean equals(Object other) {
    148         if (!(other instanceof GeneralSubtree))
    149             return false;
    150         GeneralSubtree otherGS = (GeneralSubtree)other;
    151         if (this.name == null) {
    152             if (otherGS.name != null) {
    153                 return false;
    154             }
    155         } else {
    156             if (!((this.name).equals(otherGS.name)))
    157                 return false;
    158         }
    159         if (this.minimum != otherGS.minimum)
    160             return false;
    161         if (this.maximum != otherGS.maximum)
    162             return false;
    163         return true;
    164     }
    165 
    166     /**
    167      * Returns the hash code for this GeneralSubtree.
    168      *
    169      * @return a hash code value.
    170      */
    171     public int hashCode() {
    172         if (myhash == -1) {
    173             myhash = 17;
    174             if (name != null) {
    175                 myhash = 37 * myhash + name.hashCode();
    176             }
    177             if (minimum != MIN_DEFAULT) {
    178                 myhash = 37 * myhash + minimum;
    179             }
    180             if (maximum != -1) {
    181                 myhash = 37 * myhash + maximum;
    182             }
    183         }
    184         return myhash;
    185     }
    186 
    187     /**
    188      * Encode the GeneralSubtree.
    189      *
    190      * @params out the DerOutputStream to encode this object to.
    191      */
    192     public void encode(DerOutputStream out) throws IOException {
    193         DerOutputStream seq = new DerOutputStream();
    194 
    195         name.encode(seq);
    196 
    197         if (minimum != MIN_DEFAULT) {
    198             DerOutputStream tmp = new DerOutputStream();
    199             tmp.putInteger(minimum);
    200             seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
    201                               false, TAG_MIN), tmp);
    202         }
    203         if (maximum != -1) {
    204             DerOutputStream tmp = new DerOutputStream();
    205             tmp.putInteger(maximum);
    206             seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
    207                               false, TAG_MAX), tmp);
    208         }
    209         out.write(DerValue.tag_Sequence, seq);
    210     }
    211 }
    212