1 // -*- Mode: C++; -*-
2 // Package : omniNames
3 // NamingContext_i.cc Author : Tristan Richardson (tjr)
4 //
5 // Copyright (C) 2002-2013 Apasphere Ltd
6 // Copyright (C) 1997-1999 AT&T Laboratories Cambridge
7 //
8 // This file is part of omniNames.
9 //
10 // omniNames is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, see http://www.gnu.org/licenses/
22 //
23
24 #include <string.h>
25
26 #include <assert.h>
27 #include <NamingContext_i.h>
28 #include <ObjectBinding.h>
29 #include <BindingIterator_i.h>
30 #include <omniORB4/omniURI.h>
31
32 #ifdef HAVE_STD
33 # include <iostream>
34 using namespace std;
35 #else
36 # include <iostream.h>
37 #endif
38
39 ReadersWritersLock NamingContext_i::lock;
40 NamingContext_i* NamingContext_i::headContext = (NamingContext_i*)0;
41 NamingContext_i* NamingContext_i::tailContext = (NamingContext_i*)0;
42
OMNI_USING_NAMESPACE(omni)43 OMNI_USING_NAMESPACE(omni)
44
45 //
46 // Ctor.
47 //
48 NamingContext_i::NamingContext_i(PortableServer::POA_ptr poa,
49 const PortableServer::ObjectId& id,
50 omniNameslog* l)
51 : redolog(l), nc_poa(poa)
52 {
53 headBinding = tailBinding = (ObjectBinding*)0;
54 size = 0;
55
56 WriterLock w(lock);
57
58 redolog->create(id);
59
60 prev = tailContext;
61 next = (NamingContext_i*)0;
62 tailContext = this;
63 if (prev) {
64 prev->next = this;
65 }
66 else {
67 headContext = this;
68 }
69
70 poa->activate_object_with_id(id, this);
71 }
72
73
74 //
75 // new_context().
76 //
77
78 CosNaming::NamingContext_ptr
new_context()79 NamingContext_i::new_context()
80 {
81 LOG(4, "new_context");
82
83 CORBA::Object_var ref = names_poa->create_reference(
84 CosNaming::NamingContext::_PD_repoId);
85 PortableServer::ObjectId_var id = names_poa->reference_to_id(ref);
86
87 NamingContext_i* nc = new NamingContext_i(names_poa, id, redolog);
88 CosNaming::NamingContext_ptr ncref = nc->_this();
89 nc->_remove_ref();
90
91 return ncref;
92 }
93
94
95
96 //
97 // resolve_simple() returns the ObjectBinding for a given simple name.
98 // The thread calling this must have called either lock.readerIn() or
99 // lock.writerIn() before calling this routine.
100 //
101
102 ObjectBinding*
resolve_simple(const CosNaming::Name & n)103 NamingContext_i::resolve_simple(const CosNaming::Name& n)
104 {
105 assert(n.length() == 1);
106
107 LOG(4, "resolve_simple (" << n[0].id << '.' << n[0].kind << ")");
108
109 for (ObjectBinding* ob = headBinding; ob; ob = ob->next) {
110
111 assert(ob->binding.binding_name.length() == 1);
112
113 if ((strcmp(n[0].id,ob->binding.binding_name[0].id) == 0) &&
114 (strcmp(n[0].kind,ob->binding.binding_name[0].kind) == 0))
115 {
116 LOG(4, "resolve_simple: found (" << n[0].id << '.' << n[0].kind << ")");
117
118 return ob;
119 }
120 }
121
122 LOG(4, "resolve_simple: didn't find (" << n[0].id << '.' << n[0].kind << ")");
123
124 throw CosNaming::NamingContext::NotFound(CosNaming::NamingContext::
125 missing_node, n);
126 #ifdef NEED_DUMMY_RETURN
127 return 0;
128 #endif
129 }
130
131
132 //
133 // resolve_compound() returns an object reference for the first component of
134 // the given name (which must be a context), and the rest of the name.
135 //
136
137 CosNaming::NamingContext_ptr
resolve_compound(const CosNaming::Name & n,CosNaming::Name & restOfName)138 NamingContext_i::resolve_compound(const CosNaming::Name& n,
139 CosNaming::Name& restOfName)
140 {
141 if (omniORB::trace(4)) {
142 omniORB::logger log("omniNames: ");
143 log << "resolve_compound name (";
144
145 for (unsigned int j = 0; j < n.length(); j++) {
146 if (j != 0) log << '/';
147 log << n[j].id << '.' << n[j].kind;
148 }
149 log << ")\n";
150 }
151
152 if (n.length() == 0) {
153 throw CosNaming::NamingContext::InvalidName();
154 }
155
156 CosNaming::Name contextName = n;
157 contextName.length(1);
158 restOfName.length(n.length() - 1);
159 for (unsigned int i = 0; i < n.length() - 1; i++) {
160 restOfName[i] = n[i + 1];
161 }
162
163 ObjectBinding* ob;
164
165 ReaderLock r(lock);
166
167 try {
168 ob = resolve_simple(contextName);
169 }
170 catch (CosNaming::NamingContext::NotFound& ex) {
171 ex.rest_of_name = n;
172 throw;
173 }
174
175 CosNaming::NamingContext_var context
176 = CosNaming::NamingContext::_narrow(ob->object);
177
178 if (CORBA::is_nil((CosNaming::NamingContext_ptr)context) ||
179 (ob->binding.binding_type != CosNaming::ncontext))
180 {
181 LOG(4, "resolve_compound: object (" << n[0].id << '.' << n[0].kind <<
182 ") not bound as a context; raising exception");
183 throw CosNaming::NamingContext::NotFound(CosNaming::NamingContext::
184 not_context, n);
185 }
186 return CosNaming::NamingContext::_duplicate(context);
187 }
188
189
190 //
191 // resolve.
192 //
193
194 CORBA::Object_ptr
resolve(const CosNaming::Name & n)195 NamingContext_i::resolve(const CosNaming::Name& n)
196 {
197 if (omniORB::trace(3)) {
198 omniORB::logger log("omniNames: ");
199 log << "resolve (";
200
201 for (unsigned int j = 0; j < n.length(); j++) {
202 if (j != 0) log << '/';
203 log << n[j].id << '.' << n[j].kind;
204 }
205 log << ")\n";
206 }
207
208 if (n.length() == 1) {
209 ReaderLock r(lock);
210 ObjectBinding* ob = resolve_simple(n);
211 return CORBA::Object::_duplicate(ob->object);
212 }
213 else {
214 CosNaming::Name restOfName;
215 CosNaming::NamingContext_var context = resolve_compound(n, restOfName);
216 return context->resolve(restOfName);
217 }
218 }
219
220
221 //
222 // bind_helper implements the 4 flavours of bind ([re]bind[_context]).
223 //
224
225 void
bind_helper(const CosNaming::Name & n,CORBA::Object_ptr obj,CosNaming::BindingType t,CORBA::Boolean rebind)226 NamingContext_i::bind_helper(const CosNaming::Name& n, CORBA::Object_ptr obj,
227 CosNaming::BindingType t, CORBA::Boolean rebind)
228 {
229 if (n.length() == 1) {
230 //
231 // Bind a simple name - i.e. bind object in this context.
232 //
233
234 LOG(2, "bind simple name (" << n[0].id << '.' << n[0].kind << ')');
235
236 WriterLock w(lock);
237
238 ObjectBinding* ob = 0;
239
240 try {
241 ob = resolve_simple(n);
242 if (!rebind)
243 throw CosNaming::NamingContext::AlreadyBound();
244 }
245 catch (CosNaming::NamingContext::NotFound& ex) {
246 ob = 0;
247 }
248
249 CosNaming::NamingContext_var nc = _this();
250 redolog->bind(nc, n, obj, t);
251
252 if (ob) {
253 LOG(4, "rebind: unbinding simple name (" << n[0].id << '.' << n[0].kind
254 << ')');
255 delete ob;
256 }
257
258 new ObjectBinding(n, t, obj, this);
259
260 LOG(4, "bound simple name (" << n[0].id << '.' << n[0].kind << ')');
261 }
262 else {
263 //
264 // Bind a compound name <c1;c2;...;cn> - i.e. bind object to name
265 // <c2;...;cn> in the context <c1>.
266 //
267
268 if (omniORB::trace(2)) {
269 omniORB::logger log("omniNames: ");
270 log << "bind compound name (";
271
272 for (unsigned int j = 0; j < n.length(); j++) {
273 if (j != 0) log << '/';
274 log << n[j].id << '.' << n[j].kind;
275 }
276 log << ")\n";
277 }
278
279 CosNaming::Name restOfName;
280 CosNaming::NamingContext_var context = resolve_compound(n, restOfName);
281
282 if (t == CosNaming::nobject) {
283 if (rebind)
284 context->rebind(restOfName, obj);
285 else
286 context->bind(restOfName, obj);
287 }
288 else {
289 if (rebind)
290 context->rebind_context(restOfName,
291 CosNaming::NamingContext::_narrow(obj));
292 else
293 context->bind_context(restOfName,
294 CosNaming::NamingContext::_narrow(obj));
295 }
296 }
297 }
298
299
300 //
301 // unbind()
302 //
303
304 void
unbind(const CosNaming::Name & n)305 NamingContext_i::unbind(const CosNaming::Name& n)
306 {
307 if (n.length() == 1) {
308 //
309 // Unbind a simple name - i.e. remove it from this context.
310 //
311
312 LOG(2, "unbind simple name (" << n[0].id << '.' << n[0].kind << ')');
313
314 WriterLock w(lock);
315
316 ObjectBinding* ob = resolve_simple(n);
317
318 CosNaming::NamingContext_var nc = _this();
319 redolog->unbind(nc, n);
320
321 delete ob;
322 }
323 else {
324 //
325 // Unbind a compound name <c1;c2;...;cn> - i.e. unbind the name
326 // <c2;...;cn> from the context <c1>.
327 //
328
329 if (omniORB::trace(2)) {
330 omniORB::logger log("omniNames: ");
331 log << "unbind compound name (";
332
333 for (unsigned int j = 0; j < n.length(); j++) {
334 if (j != 0) log << '/';
335 log << n[j].id << '.' << n[j].kind;
336 }
337 log << ")\n";
338 }
339 CosNaming::Name restOfName;
340 CosNaming::NamingContext_var context = resolve_compound(n, restOfName);
341
342 context->unbind(restOfName);
343 }
344 }
345
346
347 //
348 // bind_new_context()
349 //
350
351 CosNaming::NamingContext_ptr
bind_new_context(const CosNaming::Name & n)352 NamingContext_i::bind_new_context(const CosNaming::Name& n)
353 {
354 if (n.length() == 1) {
355 //
356 // Bind a new context with a simple name - i.e. create a new context and
357 // bind it in this context.
358 //
359
360 LOG(2, "bind_new_context simple name (" <<
361 n[0].id << '.' << n[0].kind << ')');
362
363 CosNaming::NamingContext_ptr nc = new_context();
364 try {
365 bind_context(n, nc);
366 }
367 catch (...) {
368 nc->destroy();
369 CORBA::release(nc);
370 throw;
371 }
372 return nc;
373 }
374 else {
375 //
376 // Bind a new context with a compound name <c1;c2;...;cn> - i.e.
377 // bind_new_context <c2;...;cn> in the context <c1>.
378 //
379
380 if (omniORB::trace(2)) {
381 omniORB::logger log("omniNames: ");
382 log << "bind_new_context compound name (";
383
384 for (unsigned int j = 0; j < n.length(); j++) {
385 if (j != 0) log << '/';
386 log << n[j].id << '.' << n[j].kind;
387 }
388 log << ")\n";
389 }
390 CosNaming::Name restOfName;
391 CosNaming::NamingContext_var context = resolve_compound(n, restOfName);
392
393 return context->bind_new_context(restOfName);
394 }
395 }
396
397
398 //
399 // destroy()
400 //
401
402 void
destroy()403 NamingContext_i::destroy()
404 {
405 LOG(4, "destroy");
406
407 WriterLock w(lock);
408
409 if (headBinding)
410 throw CosNaming::NamingContext::NotEmpty();
411
412 CosNaming::NamingContext_var nc = _this();
413 redolog->destroy(nc);
414
415 PortableServer::ObjectId_var id = nc_poa->servant_to_id(this);
416 nc_poa->deactivate_object(id);
417 }
418
419
420 //
421 // list()
422 //
423
424 void
list(CORBA::ULong how_many,CosNaming::BindingList_out bl,CosNaming::BindingIterator_out bi)425 NamingContext_i::list(CORBA::ULong how_many, CosNaming::BindingList_out bl,
426 CosNaming::BindingIterator_out bi)
427 {
428 lock.readerIn();
429
430 LOG(3, "list context: how_many = " << how_many << ", size = " << size);
431
432 CosNaming::BindingList_var all = new CosNaming::BindingList(size);
433 all->length(size);
434
435 unsigned int i;
436 ObjectBinding* ob;
437
438 for (ob = headBinding, i = 0; ob; ob = ob->next, i++) {
439 assert(i < size);
440 all[i] = ob->binding;
441 }
442
443 lock.readerOut();
444
445 if (all->length() <= how_many) {
446 // don't need an iterator. All results can go back as a
447 // result of this call
448 bi = CosNaming::BindingIterator::_nil();
449 bl = all._retn();
450 return;
451 }
452
453 BindingIterator_i* bii = new BindingIterator_i(names_poa, all._retn());
454
455 bi = bii->_this();
456 bii->_remove_ref();
457
458 bi->next_n(how_many, bl);
459 }
460
461
462 //
463 // destructor
464 //
465
~NamingContext_i()466 NamingContext_i::~NamingContext_i()
467 {
468 WriterLock w(lock);
469
470 if (prev) {
471 prev->next = next;
472 }
473 else {
474 headContext = next;
475 }
476 if (next) {
477 next->prev = prev;
478 }
479 else {
480 tailContext = prev;
481 }
482
483 while (headBinding)
484 delete headBinding;
485 }
486
487
488 //
489 // CosNaming::NamingContextExt operations
490 //
491
492 char*
to_string(const CosNaming::Name & name)493 NamingContext_i::to_string(const CosNaming::Name& name)
494 {
495 return omniURI::nameToString(name);
496 }
497
498 CosNaming::Name*
to_name(const char * sn)499 NamingContext_i::to_name(const char* sn)
500 {
501 return omniURI::stringToName(sn);
502 }
503
504 char*
to_url(const char * addr,const char * sn)505 NamingContext_i::to_url(const char* addr, const char* sn)
506 {
507 return omniURI::addrAndNameToURI(addr, sn);
508 }
509
510 CORBA::Object_ptr
resolve_str(const char * sn)511 NamingContext_i::resolve_str(const char* sn)
512 {
513 CosNaming::Name_var name = omniURI::stringToName(sn);
514 return resolve(name);
515 }
516