1 /*
2  * Copyright (c) 2002, 2018, 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.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.share.sysdict;
25 
26 import nsk.share.*;
27 
28 /**
29  * A binary tree of class loaders.
30  *
31  * @see TreeNodesDenotation
32  */
33 public class ClassLoadersBTree {
34     /**
35      * Cannot instantiate while a tree root and height
36      * are not specified.
37      *
38      * @see #ClassLoadersBTree(ClassLoader,int)
39      */
ClassLoadersBTree()40     protected ClassLoadersBTree() {
41     }
42 
43     /**
44      * Given the <tt>root</tt> loader, instantiate a binary tree
45      * of loaders up to the given tree <tt>height</tt>.
46      *
47      * @see #getHeight()
48      * @see #getRoot()
49      * @see #getLoader(String)
50      * @see #getLoader(int,int)
51      */
ClassLoadersBTree(ClassLoader root, int height)52     public ClassLoadersBTree(ClassLoader root, int height) {
53         if (height < 1)
54             throw new IllegalArgumentException("wrong height: " + height);
55         loaders = new ClassLoader [ height ] [];
56         for (int level=0; level<height; level++)
57             loaders[level] = new ClassLoader [1 << level];
58         loaders[0][0] = root;
59         generateSubtree("");
60     }
generateSubtree(String name)61     private void generateSubtree(String name) {
62         int level = name.length();
63         int height = loaders.length;
64         if (level+1 == height)
65             return;
66         String nameL = name + "L";
67         String nameR = name + "R";
68         int[] index  = denotation.indexFor(name);
69         int[] indexL = denotation.indexFor(nameL);
70         int[] indexR = denotation.indexFor(nameR);
71         // assertion: index[0]  == level
72         // assertion: indexL[0] == indexR[0] == level+1
73         int item  = index[1];
74         int itemL = indexL[1];
75         int itemR = indexR[1];
76         ClassLoader parent = loaders[level][item];
77         ClassLoader childL = new DummyClassLoader(parent);
78         ClassLoader childR = new DummyClassLoader(parent); // another item
79         loaders[level+1][itemL] = childL;
80         loaders[level+1][itemR] = childR;
81         generateSubtree(nameL);
82         generateSubtree(nameR);
83     }
84 
85     private ClassLoader loaders[][]; // loaders[0][0] is root
86     private Denotation denotation = new TreeNodesDenotation();
87 
88     /**
89      * Return the loader found at the given <tt>level</tt> of
90      * this loaders tree, and having the given <tt>item</tt>
91      * number at the enumeration of that <tt>level</tt>.
92      *
93      * <p>The value of <tt>level</tt> must be from <tt>0</tt>
94      * to <tt>getHeight()-1</tt>, and the <tt>item</tt> number
95      * must be from <tt>0</tt> to <tt>2<sup>level</sup>-1</tt>.
96      *
97      * @see #getHeight()
98      * @see #getRoot()
99      * @see #getLoader(String)
100      */
getLoader(int level, int item)101     public ClassLoader getLoader(int level, int item) {
102         return loaders[level][item];
103     }
104 
105     /**
106      * Return the loader having the giving <tt>name</tt> at
107      * the standard denotation of binary tree nodes.
108      *
109      * @see #getHeight()
110      * @see #getRoot()
111      * @see #getLoader(int,int)
112      */
getLoader(String name)113     public ClassLoader getLoader(String name) {
114         int[] index = denotation.indexFor(name);
115         int level = index[0];
116         int item  = index[1];
117         return loaders[level][item];
118     }
119 
120     /**
121      * Return the tree's height.
122      *
123      * @see #ClassLoadersBTree(ClassLoader,int)
124      * @see #getLoader(int,int)
125      * @see #getLoader(String)
126      */
getHeight()127     public int getHeight() {
128         return loaders.length;
129     }
130 
131     /**
132      * Return the tree's root loader.
133      *
134      * @see #ClassLoadersBTree(ClassLoader,int)
135      * @see #getLoader(int,int)
136      * @see #getLoader(String)
137      */
getRoot()138     public ClassLoader getRoot() {
139         return loaders[0][0];
140     }
141 }
142