1 /*
   2  * Copyright (c) 2000, 2002, 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 com.sun.jndi.dns;
  27 
  28 
  29 import java.util.Hashtable;
  30 
  31 
  32 /**
  33  * A NameNode represents a node in the DNS namespace.  Each node
  34  * has a label, which is its name relative to its parent (so the
  35  * node at Sun.COM has label "Sun").  Each node has a hashtable of
  36  * children indexed by their labels converted to lower-case.
  37  *
  38  * <p> A node may be addressed from another by giving a DnsName
  39  * consisting of the sequence of labels from one node to the other.
  40  *
  41  * <p> Each node also has an <tt>isZoneCut</tt> flag, used to indicate
  42  * if the node is a zone cut.  A zone cut is a node with an NS record
  43  * that is contained in one zone, but that actually belongs to a child zone.
  44  *
  45  * <p> All access is unsynchronized.
  46  *
  47  * @author Scott Seligman
  48  */
  49 
  50 
  51 class NameNode {
  52 
  53     private String label;               // name of this node relative to its
  54                                         // parent, or null for root of a tree
  55     private Hashtable<String,NameNode> children = null;  // child nodes
  56     private boolean isZoneCut = false;  // true if this node is a zone cut
  57     private int depth = 0;              // depth in tree (0 for root)
  58 
  59     NameNode(String label) {
  60         this.label = label;
  61     }
  62 
  63     /*
  64      * Returns a newly-allocated NameNode.  Used to allocate new nodes
  65      * in a tree.  Should be overridden in a subclass to return an object
  66      * of the subclass's type.
  67      */
  68     protected NameNode newNameNode(String label) {
  69         return new NameNode(label);
  70     }
  71 
  72     /*
  73      * Returns the name of this node relative to its parent, or null for
  74      * the root of a tree.
  75      */
  76     String getLabel() {
  77         return label;
  78     }
  79 
  80     /*
  81      * Returns the depth of this node in the tree.  The depth of the root
  82      * is 0.
  83      */
  84     int depth() {
  85         return depth;
  86     }
  87 
  88     boolean isZoneCut() {
  89         return isZoneCut;
  90     }
  91 
  92     void setZoneCut(boolean isZoneCut) {
  93         this.isZoneCut = isZoneCut;
  94     }
  95 
  96     /*
  97      * Returns the children of this node, or null if there are none.
  98      * The caller must not modify the Hashtable returned.
  99      */
 100     Hashtable<String,NameNode> getChildren() {
 101         return children;
 102     }
 103 
 104     /*
 105      * Returns the child node given the hash key (the down-cased label)
 106      * for its name relative to this node, or null if there is no such
 107      * child.
 108      */
 109     NameNode get(String key) {
 110         return (children != null)
 111             ? children.get(key)
 112             : null;
 113     }
 114 
 115     /*
 116      * Returns the node at the end of a path, or null if the
 117      * node does not exist.
 118      * The path is specified by the labels of <tt>name</tt>, beginning
 119      * at index idx.
 120      */
 121     NameNode get(DnsName name, int idx) {
 122         NameNode node = this;
 123         for (int i = idx; i < name.size() && node != null; i++) {
 124             node = node.get(name.getKey(i));
 125         }
 126         return node;
 127     }
 128 
 129     /*
 130      * Returns the node at the end of a path, creating it and any
 131      * intermediate nodes as needed.
 132      * The path is specified by the labels of <tt>name</tt>, beginning
 133      * at index idx.
 134      */
 135     NameNode add(DnsName name, int idx) {
 136         NameNode node = this;
 137         for (int i = idx; i < name.size(); i++) {
 138             String label = name.get(i);
 139             String key = name.getKey(i);
 140 
 141             NameNode child = null;
 142             if (node.children == null) {
 143                 node.children = new Hashtable<>();
 144             } else {
 145                 child = node.children.get(key);
 146             }
 147             if (child == null) {
 148                 child = newNameNode(label);
 149                 child.depth = node.depth + 1;
 150                 node.children.put(key, child);
 151             }
 152             node = child;
 153         }
 154         return node;
 155     }
 156 }