Frames | No Frames |
1: /* nContext.java -- implementation of NamingContext 2: Copyright (C) 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.CORBA.NamingService; 40: 41: import org.omg.CORBA.Object; 42: import org.omg.CosNaming.Binding; 43: import org.omg.CosNaming.BindingIteratorHolder; 44: import org.omg.CosNaming.BindingListHolder; 45: import org.omg.CosNaming.BindingType; 46: import org.omg.CosNaming.NameComponent; 47: import org.omg.CosNaming.NamingContext; 48: import org.omg.CosNaming.NamingContextOperations; 49: import org.omg.CosNaming.NamingContextPackage.AlreadyBound; 50: import org.omg.CosNaming.NamingContextPackage.CannotProceed; 51: import org.omg.CosNaming.NamingContextPackage.InvalidName; 52: import org.omg.CosNaming.NamingContextPackage.NotEmpty; 53: import org.omg.CosNaming.NamingContextPackage.NotFound; 54: import org.omg.CosNaming.NamingContextPackage.NotFoundReason; 55: import org.omg.CosNaming._NamingContextImplBase; 56: 57: import gnu.CORBA.SafeForDirectCalls; 58: 59: import java.util.Iterator; 60: import java.util.Map; 61: 62: /** 63: * This class implements the transient naming service, defined by 64: * {@link NamingContext}. The 'transient' means that the service does 65: * not store its state into the persistent memory. If the service is 66: * restarted, the named objects must be re-registered again. 67: * 68: * TODO Write the persistent naming service. 69: * 70: * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) 71: */ 72: public class TransientContext 73: extends _NamingContextImplBase 74: implements NamingContext, NamingContextOperations, SafeForDirectCalls 75: { 76: /** 77: * Use serial version UID for interoperability. 78: */ 79: private static final long serialVersionUID = 2; 80: 81: /** 82: * The already named contexts. 83: */ 84: protected final NamingMap named_contexts; 85: 86: /** 87: * The already named objects. 88: */ 89: protected final NamingMap named_objects; 90: 91: /** 92: * Create the naming conetxt with default (transient) naming maps. 93: */ 94: public TransientContext() 95: { 96: this(new NamingMap(), new NamingMap()); 97: } 98: 99: /** 100: * Create the naming conetxt with the two provided naming maps. 101: * 102: * @param context_map the map for contexts 103: * @param object_map the map for objectss 104: */ 105: public TransientContext(NamingMap context_map, NamingMap object_map) 106: { 107: named_contexts = context_map; 108: named_objects = object_map; 109: } 110: 111: /** 112: * Gives the object a name, valid in this context. 113: * 114: * @param a_name the name, being given to the object. 115: * @param an_object the object, being named. 116: * 117: * @throws AlreadyBound if the object is already named in this context. 118: * @throws InvalidName if the name has zero length or otherwise invalid. 119: */ 120: public void bind(NameComponent[] a_name, Object an_object) 121: throws NotFound, CannotProceed, InvalidName, AlreadyBound 122: { 123: if (a_name.length == 1) 124: named_objects.bind(a_name [ 0 ], an_object); 125: else 126: { 127: NamingContext context = 128: (NamingContext) named_contexts.get(a_name [ 0 ]); 129: context.bind(getSuffix(a_name), an_object); 130: } 131: } 132: 133: /** 134: * Gives a child context name, valid in this context. 135: * 136: * @param a_name the name, being given to the child context. 137: * @param a_context the child context being named. 138: * 139: * @throws AlreadyBound if the child context is already named in 140: * the current context. 141: */ 142: public void bind_context(NameComponent[] a_name, NamingContext a_context) 143: throws NotFound, CannotProceed, InvalidName, AlreadyBound 144: { 145: if (a_name.length == 1) 146: named_contexts.bind(a_name [ 0 ], a_context); 147: else 148: { 149: NamingContext context = 150: (NamingContext) named_contexts.get(a_name [ 0 ]); 151: context.bind_context(getSuffix(a_name), a_context); 152: } 153: } 154: 155: /** 156: * Create a new context and give it a given name (bound it) 157: * in the current context. 158: * 159: * The context being created is returned by calling 160: * {@link #new_context()}. 161: * 162: * @param a_name the name being given to the new context. 163: * 164: * @return the newly created context. 165: * 166: * @throws AlreadyBound if the name is already in use. 167: * @throws InvalidName if the name has zero length or otherwise invalid. 168: */ 169: public NamingContext bind_new_context(NameComponent[] a_name) 170: throws NotFound, AlreadyBound, CannotProceed, 171: InvalidName 172: { 173: if (named_contexts.containsKey(a_name [ 0 ]) || 174: named_objects.containsKey(a_name [ 0 ]) 175: ) 176: throw new AlreadyBound(); 177: 178: NamingContext child = new_context(); 179: bind_context(a_name, child); 180: return child; 181: } 182: 183: /** 184: * Destroy this context (must be empty). 185: * @throws NotEmpty if the context being destroyed is not empty. 186: */ 187: public void destroy() 188: throws NotEmpty 189: { 190: if (named_contexts.size() > 0 || named_objects.size() > 0) 191: throw new NotEmpty(); 192: } 193: 194: /** 195: * Iterate over all bindings, defined in this namind context. 196: * 197: * @param amount the maximal number of context to return in the 198: * holder a_list. The remaining bindings are accessible via iterator 199: * an_iter. If the parameter amount is zero, all bindings are accessed only 200: * via this iterator. 201: * 202: * This implementation list contexts first, then objects. 203: * 204: * @param a_list the holder, where the returned bindigs are stored. 205: * @param an_iter the iterator that can be used to access the remaining 206: * bindings. 207: */ 208: public void list(int amount, BindingListHolder a_list, 209: BindingIteratorHolder an_iter 210: ) 211: { 212: int nb = named_contexts.size() + named_objects.size(); 213: int nl = nb; 214: if (nl > amount) 215: nl = amount; 216: 217: a_list.value = new Binding[ nl ]; 218: 219: Iterator contexts = named_contexts.entries().iterator(); 220: Iterator objects = named_objects.entries().iterator(); 221: 222: // Create a binding list. 223: for (int i = 0; i < nl; i++) 224: { 225: if (contexts.hasNext()) 226: a_list.value [ i ] = mkBinding(contexts.next(), BindingType.ncontext); 227: else if (objects.hasNext()) 228: a_list.value [ i ] = mkBinding(objects.next(), BindingType.nobject); 229: else 230: throw new InternalError(); 231: } 232: 233: // Create an iterator. 234: Binding[] remainder = new Binding[ nb - nl ]; 235: int p = 0; 236: 237: while (contexts.hasNext()) 238: remainder [ p++ ] = mkBinding(contexts.next(), BindingType.ncontext); 239: 240: while (objects.hasNext()) 241: remainder [ p++ ] = mkBinding(objects.next(), BindingType.nobject); 242: 243: Binding_iterator_impl bit = new Binding_iterator_impl(remainder); 244: _orb().connect(bit); 245: an_iter.value = bit; 246: } 247: 248: /** 249: * Creates a new naming context, not bound to any name. 250: */ 251: public NamingContext new_context() 252: { 253: Ext context = new Ext(new TransientContext()); 254: 255: // Connect the context to the current ORB: 256: _orb().connect(context); 257: return context; 258: } 259: 260: /** 261: * Names or renames the object. 262: * 263: * @param a_name the new name, being given to the object 264: * in the scope of the current context. If the object is already 265: * named in this context, it is renamed. 266: * 267: * @param an_object the object, being named. 268: * 269: * @throws InvalidName if the name has zero length or otherwise invalid. 270: */ 271: public void rebind(NameComponent[] a_name, Object an_object) 272: throws NotFound, CannotProceed, InvalidName 273: { 274: if (a_name.length == 1) 275: named_objects.rebind(a_name [ 0 ], an_object); 276: else 277: { 278: NamingContext context = 279: (NamingContext) named_contexts.get(a_name [ 0 ]); 280: context.rebind(getSuffix(a_name), an_object); 281: } 282: } 283: 284: /** 285: * Names or renames the child context. 286: * If the child context is already named in 287: * the current context, it is renamed. The the name being given is in 288: * use, the old meaning of the name is discarded. 289: * 290: * @param a_name the name, being given to the child context in the scope 291: * of the current context. 292: * 293: * @param a_context the child context being named. 294: * 295: * @throws InvalidName if the name has zero length or otherwise invalid. 296: */ 297: public void rebind_context(NameComponent[] a_name, NamingContext a_context) 298: throws NotFound, CannotProceed, InvalidName 299: { 300: if (a_name.length == 1) 301: named_contexts.rebind(a_name [ 0 ], a_context); 302: else 303: { 304: NamingContext context = 305: (NamingContext) named_contexts.get(a_name [ 0 ]); 306: context.rebind_context(getSuffix(a_name), a_context); 307: } 308: } 309: 310: /** 311: * Get the object, bound to the specified name in this 312: * context. The given object must match the bound 313: * name. 314: * 315: * This implementation resolves the names as defined in specification 316: * of the CORBA naming service. This means, if the beginning of the 317: * name can be resolved to some naming context, the request is 318: * forwarded to this context, passing the unresolved name part as a 319: * parameter. In this way, it is possible to have a hierarchy of the 320: * naming services. The central services resolve the the beginning 321: * of the name. The local services resolve the remaining nodes of the 322: * name that may be relevant to some local details. It can be three or 323: * more ranks of the naming services. 324: * 325: * @param a_name the object name. 326: * 327: * @return the object, matching this name. The client 328: * usually casts or narrows (using the helper) the returned value 329: * to the more specific type. 330: * 331: * @throws NotFound if the name cannot be resolved. 332: * @throws InvalidName if the name has zero length or otherwise invalid. 333: */ 334: public Object resolve(NameComponent[] a_name) 335: throws NotFound, CannotProceed, InvalidName 336: { 337: NameValidator.check(a_name); 338: 339: if (a_name.length > 1) 340: return resolveSubContext(a_name); 341: else 342: { 343: // A single node name. 344: org.omg.CORBA.Object object; 345: 346: object = named_objects.get(a_name [ 0 ]); 347: if (object != null) 348: return object; 349: 350: object = named_contexts.get(a_name [ 0 ]); 351: if (object != null) 352: return object; 353: } 354: 355: throw new NotFound(NotFoundReason.missing_node, a_name); 356: } 357: 358: /** 359: * Removes the name from the binding context. 360: * 361: * @param a_name a name to remove. 362: * 363: * @throws InvalidName if the name has zero length or otherwise invalid. 364: */ 365: public void unbind(NameComponent[] a_name) 366: throws NotFound, CannotProceed, InvalidName 367: { 368: NameValidator.check(a_name); 369: 370: // Single node name - handle it. 371: if (a_name.length == 1) 372: { 373: if (named_objects.containsKey(a_name [ 0 ])) 374: named_objects.remove(a_name [ 0 ]); 375: else if (named_contexts.containsKey(a_name [ 0 ])) 376: named_contexts.remove(a_name [ 0 ]); 377: else 378: throw new NotFound(NotFoundReason.missing_node, a_name); 379: } 380: else 381: { 382: // Handle the first node and forward the command. 383: NamingContext subcontext = 384: (NamingContext) named_contexts.get(a_name [ 0 ]); 385: 386: if (subcontext == null) 387: throw new NotFound(NotFoundReason.missing_node, a_name); 388: 389: subcontext.unbind(getSuffix(a_name)); 390: } 391: } 392: 393: /** 394: * Get the name suffix, discarding the first member. 395: */ 396: private NameComponent[] getSuffix(NameComponent[] a_name) 397: { 398: NameComponent[] suffix = new NameComponent[ a_name.length - 1 ]; 399: System.arraycopy(a_name, 1, suffix, 0, suffix.length); 400: return suffix; 401: } 402: 403: /** 404: * Create a binding. 405: * 406: * @param an_entry the entry, defining the bound object. 407: * @param type the binding type. 408: * @return the created binding. 409: */ 410: private Binding mkBinding(java.lang.Object an_entry, BindingType type) 411: { 412: Map.Entry entry = (Map.Entry) an_entry; 413: Binding b = new Binding(); 414: 415: // The name component has always only one node (the current context) 416: b.binding_name = new NameComponent[] { (NameComponent) entry.getKey() }; 417: b.binding_type = type; 418: return b; 419: } 420: 421: /** 422: * Find the context, bound to the first name of the given 423: * name, and pass the remainder (without the first node) 424: * of the name for that context to resolve. 425: * 426: * @param a_name the name to resolve. 427: * 428: * @return the resolved context 429: */ 430: private Object resolveSubContext(NameComponent[] a_name) 431: throws NotFound, CannotProceed, InvalidName 432: { 433: // A multiple node name. 434: // This context resolves the first node only. 435: NamingContext context = (NamingContext) named_contexts.get(a_name [ 0 ]); 436: if (context == null) 437: throw new NotFound(NotFoundReason.missing_node, a_name); 438: 439: NameComponent[] suffix = getSuffix(a_name); 440: 441: return context.resolve(suffix); 442: } 443: }