xref: /haiku/src/kits/app/Handler.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2  * Copyright 2001-2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Erik Jaesler (erik@cgsoftware.com)
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 #include <TokenSpace.h>
12 
13 #include <AppDefs.h>
14 #include <Handler.h>
15 #include <Looper.h>
16 #include <Message.h>
17 #include <MessageFilter.h>
18 #include <Messenger.h>
19 #include <PropertyInfo.h>
20 
21 #include <algorithm>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <vector>
25 
26 using std::map;
27 using std::vector;
28 using BPrivate::gDefaultTokens;
29 
30 
31 static const char *kArchiveNameField = "_name";
32 
33 static property_info sHandlerPropInfo[] = {
34 	{
35 		"Suites",					// name
36 		{ B_GET_PROPERTY },			// commands
37 		{ B_DIRECT_SPECIFIER },		// specifiers
38 		NULL,						// usage
39 		0,							// extra data
40 		{ 0 },						// types
41 		{							// ctypes (compound_type)
42 			{						// ctypes[0]
43 				{					// pairs[0]
44 					{
45 						"suites",		// name
46 						B_STRING_TYPE	// type
47 					}
48 				}
49 			},
50 			{						// ctypes[1]
51 				{					// pairs[0]
52 					{
53 						"messages",
54 						B_PROPERTY_INFO_TYPE
55 					}
56 				}
57 			}
58 		},
59 		{}		// reserved
60 	},
61 	{
62 		"Messenger",
63 			{ B_GET_PROPERTY },
64 			{ B_DIRECT_SPECIFIER },
65 			NULL, 0,
66 			{ B_MESSENGER_TYPE },
67 			{},
68 			{}
69 	},
70 	{
71 		"InternalName",
72 			{ B_GET_PROPERTY },
73 			{ B_DIRECT_SPECIFIER },
74 			NULL, 0,
75 			{ B_STRING_TYPE },
76 			{},
77 			{}
78 	},
79 	{}
80 };
81 
82 bool FilterDeleter(void *filter);
83 
84 typedef map<unsigned long, vector<BHandler *> >	THandlerObserverMap;
85 typedef map<unsigned long, vector<BMessenger> >	TMessengerObserverMap;
86 
87 //------------------------------------------------------------------------------
88 // TODO: Change to BPrivate::BObserverList if possible
89 class _ObserverList {
90 	public:
91 		_ObserverList(void);
92 		~_ObserverList(void);
93 
94 		status_t SendNotices(unsigned long, BMessage const *);
95 		status_t StartObserving(BHandler *, unsigned long);
96 		status_t StartObserving(const BMessenger&, unsigned long);
97 		status_t StopObserving(BHandler *, unsigned long);
98 		status_t StopObserving(const BMessenger&, unsigned long);
99 		bool IsEmpty();
100 
101 	private:
102 		THandlerObserverMap		fHandlerMap;
103 		TMessengerObserverMap	fMessengerMap;
104 };
105 
106 
107 //	#pragma mark -
108 
109 
110 BHandler::BHandler(const char *name)
111 	: BArchivable(),
112 	fName(NULL)
113 {
114 	InitData(name);
115 }
116 
117 
118 BHandler::~BHandler()
119 {
120 	// remove all filters
121 	if (fFilters) {
122 		int32 count = fFilters->CountItems();
123 		for (int32 i = 0; i < count; i++)
124 			delete (BMessageFilter*)fFilters->ItemAtFast(i);
125 		delete fFilters;
126 	}
127 
128 	// remove all observers (the observer list manages itself)
129 	delete fObserverList;
130 
131 	// free rest
132 	free(fName);
133 	gDefaultTokens.RemoveToken(fToken);
134 }
135 
136 
137 BHandler::BHandler(BMessage *data)
138 	: BArchivable(data),
139 	fName(NULL)
140 {
141 	const char *name = NULL;
142 
143 	if (data)
144 		data->FindString(kArchiveNameField, &name);
145 
146 	InitData(name);
147 }
148 
149 
150 BArchivable *
151 BHandler::Instantiate(BMessage *data)
152 {
153 	if (!validate_instantiation(data, "BHandler"))
154 		return NULL;
155 
156 	return new BHandler(data);
157 }
158 
159 
160 status_t
161 BHandler::Archive(BMessage *data, bool deep) const
162 {
163 	status_t status = BArchivable::Archive(data, deep);
164 	if (status < B_OK)
165 		return status;
166 
167 	return data->AddString(kArchiveNameField, fName);
168 }
169 
170 
171 void
172 BHandler::MessageReceived(BMessage *message)
173 {
174 	BMessage reply(B_REPLY);
175 
176 	switch (message->what) {
177 		// ToDo: am I missing something or is the "observed" stuff handshake completely missing?
178 
179 		case B_GET_PROPERTY:
180 		{
181 			int32 cur;
182 			BMessage specifier;
183 			int32 form;
184 			const char *prop;
185 
186 			status_t err = message->GetCurrentSpecifier(&cur, &specifier, &form, &prop);
187 			bool known = false;
188 			if (cur < 0 || (strcmp(prop, "Messenger") == 0)) {
189 				err = reply.AddMessenger("result", this);
190 				known = true;
191 			} else if (strcmp(prop, "Suites") == 0) {
192 				err = GetSupportedSuites(&reply);
193 				known = true;
194 			} else if (strcmp(prop, "InternalName") == 0) {
195 				err = reply.AddString("result", Name());
196 				known = true;
197 			}
198 
199 			if (known) {
200 				reply.AddInt32("error", B_OK);
201 				message->SendReply(&reply);
202 				return;
203 			}
204 			// let's try next handler
205 			break;
206 		}
207 
208 		case B_GET_SUPPORTED_SUITES:
209 		{
210 			reply.AddInt32("error", GetSupportedSuites(&reply));
211 			message->SendReply(&reply);
212 			return;
213 		}
214 	}
215 
216 	// ToDo: there is some more work needed here (someone in the know should fill in)!
217 
218 	if (fNextHandler) {
219 		// we need to apply the next handler's filters here, too
220 		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
221 		if (target != NULL && target != this) {
222 			// TODO: we also need to make sure that "target" is not before
223 			//	us in the handler chain - at least in case it wasn't before
224 			//	the handler actually targeted with this message - this could
225 			//	get ugly, though.
226 			target->MessageReceived(message);
227 		}
228 	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
229 		&& (message->WasDropped() || message->HasSpecifiers())) {
230 		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
231 		message->PrintToStream();
232 		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
233 	}
234 }
235 
236 
237 BLooper *
238 BHandler::Looper() const
239 {
240 	return fLooper;
241 }
242 
243 
244 void
245 BHandler::SetName(const char *name)
246 {
247 	if (fName != NULL) {
248 		free(fName);
249 		fName = NULL;
250 	}
251 
252 	if (name != NULL)
253 		fName = strdup(name);
254 }
255 
256 
257 const char *
258 BHandler::Name() const
259 {
260 	return fName;
261 }
262 
263 
264 void
265 BHandler::SetNextHandler(BHandler *handler)
266 {
267 	if (!fLooper) {
268 		debugger("handler must belong to looper before setting NextHandler");
269 		return;
270 	}
271 
272 	if (!fLooper->IsLocked()) {
273 		debugger("The handler's looper must be locked before setting NextHandler");
274 		return;
275 	}
276 
277 	if (handler && fLooper != handler->Looper()) {
278 		debugger("The handler and its NextHandler must have the same looper");
279 		return;
280 	}
281 
282 	fNextHandler = handler;
283 }
284 
285 
286 BHandler *
287 BHandler::NextHandler() const
288 {
289 	return fNextHandler;
290 }
291 
292 
293 void
294 BHandler::AddFilter(BMessageFilter *filter)
295 {
296 	if (fLooper && !fLooper->IsLocked()) {
297 		debugger("Owning Looper must be locked before calling SetFilterList");
298 		return;
299 	}
300 
301 	if (fLooper != NULL)
302 		filter->SetLooper(fLooper);
303 
304 	if (!fFilters)
305 		fFilters = new BList;
306 
307 	fFilters->AddItem(filter);
308 }
309 
310 
311 bool
312 BHandler::RemoveFilter(BMessageFilter *filter)
313 {
314 	if (fLooper && !fLooper->IsLocked()) {
315 		debugger("Owning Looper must be locked before calling SetFilterList");
316 		return false;
317 	}
318 
319 	if (fFilters != NULL && fFilters->RemoveItem((void *)filter)) {
320 		filter->SetLooper(NULL);
321 		return true;
322 	}
323 
324 	return false;
325 }
326 
327 
328 void
329 BHandler::SetFilterList(BList* filters)
330 {
331 	if (fLooper && !fLooper->IsLocked()) {
332 		debugger("Owning Looper must be locked before calling SetFilterList");
333 		return;
334 	}
335 
336 	/**
337 		@note	I would like to use BObjectList internally, but this function is
338 				spec'd such that fFilters would get deleted and then assigned
339 				'filters', which would obviously mess this up.  Wondering if
340 				anyone ever assigns a list of filters and then checks against
341 				FilterList() to see if they are the same.
342 	 */
343 
344 	// TODO: Explore issues with using BObjectList
345 	if (fFilters) {
346 		fFilters->DoForEach(FilterDeleter);
347 		delete fFilters;
348 	}
349 
350 	fFilters = filters;
351 	if (fFilters) {
352 		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
353 			BMessageFilter *filter =
354 				static_cast<BMessageFilter *>(fFilters->ItemAt(i));
355 			if (filter != NULL)
356 				filter->SetLooper(fLooper);
357 		}
358 	}
359 }
360 
361 
362 BList *
363 BHandler::FilterList()
364 {
365 	return fFilters;
366 }
367 
368 
369 bool
370 BHandler::LockLooper()
371 {
372 	BLooper *looper = fLooper;
373 	// Locking the looper also makes sure that the looper is valid
374 	if (looper != NULL && looper->Lock()) {
375 		// Have we locked the right looper? That's as far as the
376 		// "pseudo-atomic" operation mentioned in the BeBook.
377 		if (fLooper == looper)
378 			return true;
379 
380 		// we locked the wrong looper, bail out
381 		looper->Unlock();
382 	}
383 
384 	return false;
385 }
386 
387 
388 status_t
389 BHandler::LockLooperWithTimeout(bigtime_t timeout)
390 {
391 	BLooper *looper = fLooper;
392 	if (looper == NULL)
393 		return B_BAD_VALUE;
394 
395 	status_t status = looper->LockWithTimeout(timeout);
396 	if (status != B_OK)
397 		return status;
398 
399 	if (fLooper != looper) {
400 		// we locked the wrong looper, bail out
401 		looper->Unlock();
402 		return B_MISMATCHED_VALUES;
403 	}
404 
405 	return B_OK;
406 }
407 
408 
409 void
410 BHandler::UnlockLooper()
411 {
412 	// The looper is locked at this point, and cannot change
413 	if (fLooper != NULL)
414 		fLooper->Unlock();
415 }
416 
417 
418 BHandler *
419 BHandler::ResolveSpecifier(BMessage *msg, int32 index,
420 	BMessage *specifier, int32 form, const char *property)
421 {
422 	// Straight from the BeBook
423 	BPropertyInfo propertyInfo(sHandlerPropInfo);
424 	if (propertyInfo.FindMatch(msg, index, specifier, form, property) >= 0)
425 		return this;
426 
427 	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
428 	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
429 	reply.AddString("message", "Didn't understand the specifier(s)");
430 	msg->SendReply(&reply);
431 
432 	return NULL;
433 }
434 
435 
436 status_t
437 BHandler::GetSupportedSuites(BMessage *data)
438 {
439 /**
440 	@note	This is the output from the original implementation (calling
441 			PrintToStream() on both data and the contained BPropertyInfo):
442 
443 BMessage: what =  (0x0, or 0)
444     entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
445     entry       messages, type='SCTD', c=1, size= 0,
446       property   commands                       types                specifiers
447 --------------------------------------------------------------------------------
448         Suites   PGET                                               1
449                  (RTSC,suites)
450                  (DTCS,messages)
451 
452      Messenger   PGET                          GNSM                 1
453   InternalName   PGET                          RTSC                 1
454 
455 			With a good deal of trial and error, I determined that the
456 			parenthetical clauses are entries in the 'ctypes' field of
457 			property_info.  'ctypes' is an array of 'compound_type', which
458 			contains an array of 'field_pair's.  I haven't the foggiest what
459 			either 'compound_type' or 'field_pair' is for, being as the
460 			scripting docs are so bloody horrible.  The corresponding
461 			property_info array is declared in the globals section.
462  */
463 
464 	status_t err = B_OK;
465 	if (!data)
466 		err = B_BAD_VALUE;
467 
468 	if (!err) {
469 		err = data->AddString("suites", "suite/vnd.Be-handler");
470 		if (!err) {
471 			BPropertyInfo propertyInfo(sHandlerPropInfo);
472 			err = data->AddFlat("messages", &propertyInfo);
473 		}
474 	}
475 
476 	return err;
477 }
478 
479 
480 status_t
481 BHandler::StartWatching(BMessenger messenger, uint32 what)
482 {
483 	if (fObserverList == NULL)
484 		fObserverList = new _ObserverList;
485 	return fObserverList->StartObserving(messenger, what);
486 }
487 
488 
489 status_t
490 BHandler::StartWatchingAll(BMessenger messenger)
491 {
492 	return StartWatching(messenger, B_OBSERVER_OBSERVE_ALL);
493 }
494 
495 
496 status_t
497 BHandler::StopWatching(BMessenger messenger, uint32 what)
498 {
499 	if (fObserverList == NULL)
500 		fObserverList = new _ObserverList;
501 	return fObserverList->StopObserving(messenger, what);
502 }
503 
504 
505 status_t
506 BHandler::StopWatchingAll(BMessenger messenger)
507 {
508 	return StopWatching(messenger, B_OBSERVER_OBSERVE_ALL);
509 }
510 
511 
512 status_t
513 BHandler::StartWatching(BHandler *handler, uint32 what)
514 {
515 	if (fObserverList == NULL)
516 		fObserverList = new _ObserverList;
517 	return fObserverList->StartObserving(handler, what);
518 }
519 
520 
521 status_t
522 BHandler::StartWatchingAll(BHandler *handler)
523 {
524 	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
525 }
526 
527 
528 status_t
529 BHandler::StopWatching(BHandler *handler, uint32 what)
530 {
531 	if (fObserverList == NULL)
532 		fObserverList = new _ObserverList;
533 	return fObserverList->StopObserving(handler, what);
534 }
535 
536 
537 status_t
538 BHandler::StopWatchingAll(BHandler *handler)
539 {
540 	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
541 }
542 
543 
544 status_t
545 BHandler::Perform(perform_code d, void *arg)
546 {
547 	return BArchivable::Perform(d, arg);
548 }
549 
550 
551 void
552 BHandler::SendNotices(uint32 what, const BMessage *msg)
553 {
554 	if (fObserverList != NULL)
555 		fObserverList->SendNotices(what, msg);
556 }
557 
558 
559 bool
560 BHandler::IsWatched() const
561 {
562 	return fObserverList && !fObserverList->IsEmpty();
563 }
564 
565 
566 void
567 BHandler::InitData(const char *name)
568 {
569 	SetName(name);
570 
571 	fLooper = NULL;
572 	fNextHandler = NULL;
573 	fFilters = NULL;
574 	fObserverList = NULL;
575 
576 	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
577 }
578 
579 
580 BHandler::BHandler(const BHandler &)
581 {
582 	// No copy construction allowed.
583 }
584 
585 
586 BHandler &
587 BHandler::operator=(const BHandler &)
588 {
589 	// No assignments allowed.
590 	return *this;
591 }
592 
593 
594 void
595 BHandler::SetLooper(BLooper *looper)
596 {
597 	fLooper = looper;
598 
599 	if (fFilters) {
600 		for (int32 i = 0; i < fFilters->CountItems(); i++)
601 			static_cast<BMessageFilter *>(fFilters->ItemAtFast(i))->SetLooper(looper);
602 	}
603 }
604 
605 
606 #ifdef __INTEL__
607 // binary compatibility with R4.5
608 extern "C" void _ReservedHandler1__8BHandler(void) {}
609 #endif
610 
611 void BHandler::_ReservedHandler2() {}
612 void BHandler::_ReservedHandler3() {}
613 void BHandler::_ReservedHandler4() {}
614 
615 
616 //	#pragma mark -
617 
618 
619 _ObserverList::_ObserverList(void)
620 {
621 }
622 
623 
624 _ObserverList::~_ObserverList(void)
625 {
626 }
627 
628 
629 status_t
630 _ObserverList::SendNotices(unsigned long what, BMessage const *message)
631 {
632 	// Having to new a temporary is really irritating ...
633 	BMessage *copyMsg = NULL;
634 	if (message) {
635 		copyMsg = new BMessage(*message);
636 		copyMsg->what = B_OBSERVER_NOTICE_CHANGE;
637 		copyMsg->AddInt32(B_OBSERVE_ORIGINAL_WHAT, message->what);
638 	} else
639 		copyMsg = new BMessage(B_OBSERVER_NOTICE_CHANGE);
640 
641 	copyMsg->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
642 
643 	vector<BHandler *> &handlers = fHandlerMap[what];
644 	for (uint32 i = 0; i < handlers.size(); ++i) {
645 		BMessenger msgr(handlers[i]);
646 		msgr.SendMessage(copyMsg);
647 	}
648 
649 	vector<BMessenger> &messengers = fMessengerMap[what];
650 	for (uint32 i = 0; i < messengers.size(); ++i)
651 		messengers[i].SendMessage(copyMsg);
652 
653 	// We have to send the message also to the handlers
654 	// and messengers which were subscribed to ALL events,
655 	// since they aren't caught by the above loops.
656 	// TODO: cleanup
657 	vector<BHandler *> &handlersAll = fHandlerMap[B_OBSERVER_OBSERVE_ALL];
658 	for (uint32 i = 0; i < handlersAll.size(); ++i) {
659 		BMessenger msgr(handlersAll[i]);
660 		msgr.SendMessage(copyMsg);
661 	}
662 
663 	vector<BMessenger> &messengersAll = fMessengerMap[B_OBSERVER_OBSERVE_ALL];
664 	for (uint32 i = 0; i < messengersAll.size(); ++i)
665 		messengers[i].SendMessage(copyMsg);
666 
667 	// Gotta make sure to clean up the annoying temporary ...
668 	delete copyMsg;
669 
670 	return B_OK;
671 }
672 
673 
674 status_t
675 _ObserverList::StartObserving(BHandler *handler, unsigned long what)
676 {
677 	if (handler == NULL)
678 		return B_BAD_HANDLER;
679 
680 	vector<BHandler*> &handlers = fHandlerMap[what];
681 
682 	vector<BHandler*>::iterator iter;
683 	iter = find(handlers.begin(), handlers.end(), handler);
684 	if (iter != handlers.end()) {
685 		// TODO: verify
686 		return B_OK;
687 	}
688 
689 	handlers.push_back(handler);
690 	return B_OK;
691 }
692 
693 
694 status_t
695 _ObserverList::StartObserving(const BMessenger &messenger,
696 	unsigned long what)
697 {
698 	vector<BMessenger> &messengers = fMessengerMap[what];
699 
700 	vector<BMessenger>::iterator iter;
701 	iter = find(messengers.begin(), messengers.end(), messenger);
702 	if (iter != messengers.end()) {
703 		// TODO: verify
704 		return B_OK;
705 	}
706 
707 	messengers.push_back(messenger);
708 	return B_OK;
709 }
710 
711 
712 status_t
713 _ObserverList::StopObserving(BHandler *handler, unsigned long what)
714 {
715 	if (handler == NULL)
716 		return B_BAD_HANDLER;
717 
718 	vector<BHandler*> &handlers = fHandlerMap[what];
719 
720 	vector<BHandler*>::iterator iter;
721 	iter = find(handlers.begin(), handlers.end(), handler);
722 	if (iter != handlers.end()) {
723 		handlers.erase(iter);
724 		if (handlers.empty())
725 			fHandlerMap.erase(what);
726 
727 		return B_OK;
728 	}
729 
730 	return B_BAD_HANDLER;
731 }
732 
733 
734 status_t
735 _ObserverList::StopObserving(const BMessenger &messenger,
736 	unsigned long what)
737 {
738 	// ???:	What if you call StartWatching(MyMsngr, aWhat) and then call
739 	//		StopWatchingAll(MyMsnger)?  Will MyMsnger be removed from the aWhat
740 	//		watcher list?  For now, we'll assume that they're discreet lists
741 	//		which do no cross checking; i.e., MyMsnger would *not* be removed in
742 	//		this scenario.
743 	vector<BMessenger> &messengers = fMessengerMap[what];
744 
745 	vector<BMessenger>::iterator iter;
746 	iter = find(messengers.begin(), messengers.end(), messenger);
747 	if (iter != messengers.end()) {
748 		messengers.erase(iter);
749 		if (messengers.empty())
750 			fMessengerMap.erase(what);
751 
752 		return B_OK;
753 	}
754 
755 	return B_BAD_HANDLER;
756 }
757 
758 
759 bool
760 _ObserverList::IsEmpty()
761 {
762 	return fHandlerMap.empty() && fMessengerMap.empty();
763 }
764 
765 
766 //	#pragma mark -
767 
768 
769 bool
770 FilterDeleter(void *_filter)
771 {
772 	delete static_cast<BMessageFilter *>(_filter);
773 	return false;
774 }
775 
776