001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.core.ivm.naming;
017:
018: public class NameNode implements java.io.Serializable {
019: private String atomicName;
020: private int atomicHash;
021: private NameNode lessTree;
022: private NameNode grtrTree;
023: private NameNode subTree;
024: private NameNode parentTree;
025: private NameNode parent;
026: private Object myObject;
027: private transient IvmContext myContext;
028: private boolean unbound;
029:
030: public NameNode(NameNode parent, ParsedName name, Object obj,
031: NameNode parentTree) {
032: atomicName = name.getComponent();
033: atomicHash = name.getComponentHashCode();
034: this .parent = parent;
035: this .parentTree = parentTree;
036: if (name.next())
037: subTree = new NameNode(this , name, obj, this );
038: else
039: myObject = obj;
040: }
041:
042: public Object getBinding() {
043: if (myObject != null)
044: return myObject;// if NameNode has an object it must be a binding
045: else {
046: if (myContext == null)
047: myContext = new IvmContext(this );
048: return myContext;
049: }
050: }
051:
052: public Object resolve(ParsedName name)
053: throws javax.naming.NameNotFoundException {
054: int compareResult = name.compareTo(atomicHash);
055:
056: if (compareResult == ParsedName.IS_EQUAL
057: && name.getComponent().equals(atomicName)) {// hashcodes and String valuse are equal
058: if (name.next()) {
059: if (subTree == null)
060: throw new javax.naming.NameNotFoundException(
061: "Cannot resolve " + name);
062: return subTree.resolve(name);
063: } else if (unbound) {
064: throw new javax.naming.NameNotFoundException(
065: "Cannot resolve " + name);
066: } else {
067: return getBinding();
068: }
069: } else if (compareResult == ParsedName.IS_LESS) {// parsed hash is less than
070: if (lessTree == null)
071: throw new javax.naming.NameNotFoundException(
072: "Cannot resolve " + name);
073: return lessTree.resolve(name);
074:
075: } else {//ParsedName.IS_GREATER
076:
077: if (grtrTree == null)
078: throw new javax.naming.NameNotFoundException(
079: "Cannot resolve " + name);
080: return grtrTree.resolve(name);
081: }
082: }
083:
084: public void bind(ParsedName name, Object obj)
085: throws javax.naming.NameAlreadyBoundException {
086: int compareResult = name.compareTo(atomicHash);
087: if (compareResult == ParsedName.IS_EQUAL
088: && name.getComponent().equals(atomicName)) {
089: if (name.next()) {
090: if (myObject != null) {
091: throw new javax.naming.NameAlreadyBoundException();
092: }
093: if (subTree == null)
094: subTree = new NameNode(this , name, obj, this );
095: else
096: subTree.bind(name, obj);
097: } else {
098: if (subTree != null) {
099: throw new javax.naming.NameAlreadyBoundException();
100: }
101: if (myObject != null) {
102: throw new javax.naming.NameAlreadyBoundException();
103: }
104: unbound = false;
105: myObject = obj;// bind the object to this node
106: }
107: } else if (compareResult == ParsedName.IS_LESS) {
108: if (lessTree == null)
109: lessTree = new NameNode(this .parent, name, obj, this );
110: else
111: lessTree.bind(name, obj);
112: } else {//ParsedName.IS_GREATER ...
113:
114: if (grtrTree == null)
115: grtrTree = new NameNode(this .parent, name, obj, this );
116: else
117: grtrTree.bind(name, obj);
118: }
119: }
120:
121: public int compareTo(int otherHash) {
122: if (atomicHash == otherHash)
123: return 0;
124: else if (atomicHash > otherHash)
125: return 1;
126: else
127: return -1;
128: }
129:
130: private void bind(NameNode node) {
131: int compareResult = node.compareTo(atomicHash);
132:
133: // This seems to be needed because of an inbalanced way
134: // in which we use bind/unbind/lookup. Bind/unbind require
135: // the prefix of the node to be appended because lookup
136: // will add the prefix when doing a lookup. Seems if
137: // we got rid of the prefix usage in lookup, we could
138: // kill this if block and would have more balanced
139: // btrees
140: if (node.parent == this ) {
141: compareResult = ParsedName.IS_EQUAL;
142: }
143:
144: if (compareResult == ParsedName.IS_EQUAL) {
145: if (subTree == null) {
146: subTree = node;
147: subTree.parentTree = this ;
148: } else {
149: subTree.bind(node);
150: }
151: } else if (compareResult == ParsedName.IS_LESS) {
152: if (lessTree == null) {
153: lessTree = node;
154: lessTree.parentTree = this ;
155: } else {
156: lessTree.bind(node);
157: }
158: } else {//ParsedName.IS_GREATER ...
159:
160: if (grtrTree == null) {
161: grtrTree = node;
162: grtrTree.parentTree = this ;
163: } else {
164: grtrTree.bind(node);
165: }
166: }
167: }
168:
169: public void unbind(ParsedName name)
170: throws javax.naming.NameAlreadyBoundException {
171: int compareResult = name.compareTo(atomicHash);
172: if (compareResult == ParsedName.IS_EQUAL
173: && name.getComponent().equals(atomicName)) {
174: if (name.next()) {
175: if (subTree != null) {
176: subTree.unbind(name);
177: }
178: } else {
179: unbound = true;
180: myObject = null;
181: parentTree.unbind(this );
182: }
183: } else if (compareResult == ParsedName.IS_LESS) {
184: if (lessTree != null) {
185: lessTree.unbind(name);
186: }
187: } else {//ParsedName.IS_GREATER ...
188:
189: if (grtrTree != null)
190: grtrTree.unbind(name);
191: }
192: }
193:
194: private void unbind(NameNode node) {
195: if (subTree == node) {
196: subTree = null;
197: } else if (grtrTree == node) {
198: grtrTree = null;
199: } else if (lessTree == node) {
200: lessTree = null;
201: }
202: rebalance(this , node);
203: }
204:
205: private void rebalance(NameNode tree, NameNode node) {
206: if (node.subTree != null) {
207: tree.bind(node.subTree);
208: }
209: if (node.lessTree != null) {
210: this .bind(node.lessTree);
211: }
212: if (node.grtrTree != null) {
213: this .bind(node.grtrTree);
214: }
215: }
216:
217: protected void prune() {
218: prune(this );
219: }
220:
221: private void prune(NameNode until) {
222: if (subTree != null) {
223: subTree.prune(until);
224: }
225: if (lessTree != null) {
226: lessTree.prune(until);
227: }
228: if (grtrTree != null) {
229: grtrTree.prune(until);
230: }
231:
232: if (this == until)
233: return;
234:
235: if (!hasChildren() && myObject == null) {
236: parentTree.unbind(this );
237: }
238: }
239:
240: private boolean hasChildren() {
241: return hasChildren(this );
242: }
243:
244: private boolean hasChildren(NameNode node) {
245: if (subTree != null && subTree.hasChildren(node))
246: return true;
247: if (grtrTree != null && grtrTree.hasChildren(node))
248: return true;
249: if (lessTree != null && lessTree.hasChildren(node))
250: return true;
251:
252: return (parent == node);
253: }
254:
255: protected void clearCache() {
256: if (myContext != null) {
257: myContext.fastCache.clear();
258: }
259: if (grtrTree != null) {
260: grtrTree.clearCache();
261: }
262: if (lessTree != null) {
263: lessTree.clearCache();
264: }
265: if (subTree != null) {
266: subTree.clearCache();
267: }
268: }
269:
270: public IvmContext createSubcontext(ParsedName name)
271: throws javax.naming.NameAlreadyBoundException {
272: try {
273: bind(name, null);
274: name.reset();
275: return (IvmContext) resolve(name);
276: } catch (javax.naming.NameNotFoundException exception) {
277: exception.printStackTrace();
278: throw new RuntimeException(exception);
279: }
280: }
281:
282: public String getAtomicName() {
283: return atomicName;
284: }
285:
286: public NameNode getLessTree() {
287: return lessTree;
288: }
289:
290: public NameNode getGrtrTree() {
291: return grtrTree;
292: }
293:
294: public NameNode getSubTree() {
295: return subTree;
296: }
297:
298: public NameNode getParent() {
299: return parent;
300: }
301:
302: }
|