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
26package com.sun.jndi.dns;
27
28
29import 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 {@code isZoneCut} 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
51class 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 {@code name}, 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 {@code name}, 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}
157