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