xref: /haiku/src/kits/app/Handler.cpp (revision 0e50eab75e25d0d82090e22dbff766dfaa6f5e86)
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 			if (err == B_OK) {
188 				bool known = false;
189 				if (strcmp(prop, "Suites") == 0) {
190 					err = GetSupportedSuites(&reply);
191 					known = true;
192 				} else if (strcmp(prop, "Messenger") == 0) {
193 					err = reply.AddMessenger("result", this);
194 					known = true;
195 				} else if (strcmp(prop, "InternalName") == 0) {
196 					err = reply.AddString("result", Name());
197 					known = true;
198 				}
199 
200 				if (known) {
201 					reply.AddInt32("error", B_OK);
202 					message->SendReply(&reply);
203 					return;
204 				}
205 				// let's try next handler
206 			}
207 			break;
208 		}
209 
210 		case B_GET_SUPPORTED_SUITES:
211 		{
212 			reply.AddInt32("error", GetSupportedSuites(&reply));
213 			message->SendReply(&reply);
214 			return;
215 		}
216 	}
217 
218 	// ToDo: there is some more work needed here (someone in the know should fill in)!
219 
220 	if (fNextHandler) {
221 		// we need to apply the next handler's filters here, too
222 		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
223 		if (target != NULL && target != this) {
224 			// TODO: we also need to make sure that "target" is not before
225 			//	us in the handler chain - at least in case it wasn't before
226 			//	the handler actually targeted with this message - this could
227 			//	get ugly, though.
228 			target->MessageReceived(message);
229 		}
230 	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
231 		&& (message->WasDropped() || message->HasSpecifiers())) {
232 		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
233 		message->PrintToStream();
234 		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
235 	}
236 }
237 
238 
239 BLooper *
240 BHandler::Looper() const
241 {
242 	return fLooper;
243 }
244 
245 
246 void
247 BHandler::SetName(const char *name)
248 {
249 	if (fName != NULL) {
250 		free(fName);
251 		fName = NULL;
252 	}
253 
254 	if (name != NULL)
255 		fName = strdup(name);
256 }
257 
258 
259 const char *
260 BHandler::Name() const
261 {
262 	return fName;
263 }
264 
265 
266 void
267 BHandler::SetNextHandler(BHandler *handler)
268 {
269 	if (!fLooper) {
270 		debugger("handler must belong to looper before setting NextHandler");
271 		return;
272 	}
273 
274 	if (!fLooper->IsLocked()) {
275 		debugger("The handler's looper must be locked before setting NextHandler");
276 		return;
277 	}
278 
279 	if (handler && fLooper != handler->Looper()) {
280 		debugger("The handler and its NextHandler must have the same looper");
281 		return;
282 	}
283 
284 	fNextHandler = handler;
285 }
286 
287 
288 BHandler *
289 BHandler::NextHandler() const
290 {
291 	return fNextHandler;
292 }
293 
294 
295 void
296 BHandler::AddFilter(BMessageFilter *filter)
297 {
298 	if (fLooper && !fLooper->IsLocked()) {
299 		debugger("Owning Looper must be locked before calling SetFilterList");
300 		return;
301 	}
302 
303 	if (fLooper != NULL)
304 		filter->SetLooper(fLooper);
305 
306 	if (!fFilters)
307 		fFilters = new BList;
308 
309 	fFilters->AddItem(filter);
310 }
311 
312 
313 bool
314 BHandler::RemoveFilter(BMessageFilter *filter)
315 {
316 	if (fLooper && !fLooper->IsLocked()) {
317 		debugger("Owning Looper must be locked before calling SetFilterList");
318 		return false;
319 	}
320 
321 	if (fFilters != NULL && fFilters->RemoveItem((void *)filter)) {
322 		filter->SetLooper(NULL);
323 		return true;
324 	}
325 
326 	return false;
327 }
328 
329 
330 void
331 BHandler::SetFilterList(BList* filters)
332 {
333 	if (fLooper && !fLooper->IsLocked()) {
334 		debugger("Owning Looper must be locked before calling SetFilterList");
335 		return;
336 	}
337 
338 	/**
339 		@note	I would like to use BObjectList internally, but this function is
340 				spec'd such that fFilters would get deleted and then assigned
341 				'filters', which would obviously mess this up.  Wondering if
342 				anyone ever assigns a list of filters and then checks against
343 				FilterList() to see if they are the same.
344 	 */
345 
346 	// TODO: Explore issues with using BObjectList
347 	if (fFilters) {
348 		fFilters->DoForEach(FilterDeleter);
349 		delete fFilters;
350 	}
351 
352 	fFilters = filters;
353 	if (fFilters) {
354 		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
355 			BMessageFilter *filter =
356 				static_cast<BMessageFilter *>(fFilters->ItemAt(i));
357 			if (filter != NULL)
358 				filter->SetLooper(fLooper);
359 		}
360 	}
361 }
362 
363 
364 BList *
365 BHandler::FilterList()
366 {
367 	return fFilters;
368 }
369 
370 
371 bool
372 BHandler::LockLooper()
373 {
374 	BLooper *looper = fLooper;
375 	// Locking the looper also makes sure that the looper is valid
376 	if (looper != NULL && looper->Lock()) {
377 		// Have we locked the right looper? That's as far as the
378 		// "pseudo-atomic" operation mentioned in the BeBook.
379 		if (fLooper == looper)
380 			return true;
381 
382 		// we locked the wrong looper, bail out
383 		looper->Unlock();
384 	}
385 
386 	return false;
387 }
388 
389 
390 status_t
391 BHandler::LockLooperWithTimeout(bigtime_t timeout)
392 {
393 	BLooper *looper = fLooper;
394 	if (looper == NULL)
395 		return B_BAD_VALUE;
396 
397 	status_t status = looper->LockWithTimeout(timeout);
398 	if (status != B_OK)
399 		return status;
400 
401 	if (fLooper != looper) {
402 		// we locked the wrong looper, bail out
403 		looper->Unlock();
404 		return B_MISMATCHED_VALUES;
405 	}
406 
407 	return B_OK;
408 }
409 
410 
411 void
412 BHandler::UnlockLooper()
413 {
414 	// The looper is locked at this point, and cannot change
415 	if (fLooper != NULL)
416 		fLooper->Unlock();
417 }
418 
419 
420 BHandler *
421 BHandler::ResolveSpecifier(BMessage *msg, int32 index,
422 	BMessage *specifier, int32 form, const char *property)
423 {
424 	// Straight from the BeBook
425 	BPropertyInfo propertyInfo(sHandlerPropInfo);
426 	if (propertyInfo.FindMatch(msg, index, specifier, form, property) >= 0)
427 		return this;
428 
429 	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
430 	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
431 	reply.AddString("message", "Didn't understand the specifier(s)");
432 	msg->SendReply(&reply);
433 
434 	return NULL;
435 }
436 
437 
438 status_t
439 BHandler::GetSupportedSuites(BMessage *data)
440 {
441 /**
442 	@note	This is the output from the original implementation (calling
443 			PrintToStream() on both data and the contained BPropertyInfo):
444 
445 BMessage: what =  (0x0, or 0)
446     entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
447     entry       messages, type='SCTD', c=1, size= 0,
448       property   commands                       types                specifiers
449 --------------------------------------------------------------------------------
450         Suites   PGET                                               1
451                  (RTSC,suites)
452                  (DTCS,messages)
453 
454      Messenger   PGET                          GNSM                 1
455   InternalName   PGET                          RTSC                 1
456 
457 			With a good deal of trial and error, I determined that the
458 			parenthetical clauses are entries in the 'ctypes' field of
459 			property_info.  'ctypes' is an array of 'compound_type', which
460 			contains an array of 'field_pair's.  I haven't the foggiest what
461 			either 'compound_type' or 'field_pair' is for, being as the
462 			scripting docs are so bloody horrible.  The corresponding
463 			property_info array is declared in the globals section.
464  */
465 
466 	status_t err = B_OK;
467 	if (!data)
468 		err = B_BAD_VALUE;
469 
470 	if (!err) {
471 		err = data->AddString("suites", "suite/vnd.Be-handler");
472 		if (!err) {
473 			BPropertyInfo propertyInfo(sHandlerPropInfo);
474 			err = data->AddFlat("messages", &propertyInfo);
475 		}
476 	}
477 
478 	return err;
479 }
480 
481 
482 status_t
483 BHandler::StartWatching(BMessenger messenger, uint32 what)
484 {
485 	if (fObserverList == NULL)
486 		fObserverList = new _ObserverList;
487 	return fObserverList->StartObserving(messenger, what);
488 }
489 
490 
491 status_t
492 BHandler::StartWatchingAll(BMessenger messenger)
493 {
494 	return StartWatching(messenger, B_OBSERVER_OBSERVE_ALL);
495 }
496 
497 
498 status_t
499 BHandler::StopWatching(BMessenger messenger, uint32 what)
500 {
501 	if (fObserverList == NULL)
502 		fObserverList = new _ObserverList;
503 	return fObserverList->StopObserving(messenger, what);
504 }
505 
506 
507 status_t
508 BHandler::StopWatchingAll(BMessenger messenger)
509 {
510 	return StopWatching(messenger, B_OBSERVER_OBSERVE_ALL);
511 }
512 
513 
514 status_t
515 BHandler::StartWatching(BHandler *handler, uint32 what)
516 {
517 	if (fObserverList == NULL)
518 		fObserverList = new _ObserverList;
519 	return fObserverList->StartObserving(handler, what);
520 }
521 
522 
523 status_t
524 BHandler::StartWatchingAll(BHandler *handler)
525 {
526 	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
527 }
528 
529 
530 status_t
531 BHandler::StopWatching(BHandler *handler, uint32 what)
532 {
533 	if (fObserverList == NULL)
534 		fObserverList = new _ObserverList;
535 	return fObserverList->StopObserving(handler, what);
536 }
537 
538 
539 status_t
540 BHandler::StopWatchingAll(BHandler *handler)
541 {
542 	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
543 }
544 
545 
546 status_t
547 BHandler::Perform(perform_code d, void *arg)
548 {
549 	return BArchivable::Perform(d, arg);
550 }
551 
552 
553 void
554 BHandler::SendNotices(uint32 what, const BMessage *msg)
555 {
556 	if (fObserverList != NULL)
557 		fObserverList->SendNotices(what, msg);
558 }
559 
560 
561 bool
562 BHandler::IsWatched() const
563 {
564 	return fObserverList && !fObserverList->IsEmpty();
565 }
566 
567 
568 void
569 BHandler::InitData(const char *name)
570 {
571 	SetName(name);
572 
573 	fLooper = NULL;
574 	fNextHandler = NULL;
575 	fFilters = NULL;
576 	fObserverList = NULL;
577 
578 	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
579 }
580 
581 
582 BHandler::BHandler(const BHandler &)
583 {
584 	// No copy construction allowed.
585 }
586 
587 
588 BHandler &
589 BHandler::operator=(const BHandler &)
590 {
591 	// No assignments allowed.
592 	return *this;
593 }
594 
595 
596 void
597 BHandler::SetLooper(BLooper *looper)
598 {
599 	fLooper = looper;
600 
601 	if (fFilters) {
602 		for (int32 i = 0; i < fFilters->CountItems(); i++)
603 			static_cast<BMessageFilter *>(fFilters->ItemAtFast(i))->SetLooper(looper);
604 	}
605 }
606 
607 
608 #ifdef __INTEL__
609 // binary compatibility with R4.5
610 extern "C" void _ReservedHandler1__8BHandler(void) {}
611 #endif
612 
613 void BHandler::_ReservedHandler2() {}
614 void BHandler::_ReservedHandler3() {}
615 void BHandler::_ReservedHandler4() {}
616 
617 
618 //	#pragma mark -
619 
620 
621 _ObserverList::_ObserverList(void)
622 {
623 }
624 
625 
626 _ObserverList::~_ObserverList(void)
627 {
628 }
629 
630 
631 status_t
632 _ObserverList::SendNotices(unsigned long what, BMessage const *message)
633 {
634 	// Having to new a temporary is really irritating ...
635 	BMessage *copyMsg = NULL;
636 	if (message) {
637 		copyMsg = new BMessage(*message);
638 		copyMsg->what = B_OBSERVER_NOTICE_CHANGE;
639 		copyMsg->AddInt32(B_OBSERVE_ORIGINAL_WHAT, message->what);
640 	} else
641 		copyMsg = new BMessage(B_OBSERVER_NOTICE_CHANGE);
642 
643 	copyMsg->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
644 
645 	vector<BHandler *> &handlers = fHandlerMap[what];
646 	for (uint32 i = 0; i < handlers.size(); ++i) {
647 		BMessenger msgr(handlers[i]);
648 		msgr.SendMessage(copyMsg);
649 	}
650 
651 	vector<BMessenger> &messengers = fMessengerMap[what];
652 	for (uint32 i = 0; i < messengers.size(); ++i)
653 		messengers[i].SendMessage(copyMsg);
654 
655 	// We have to send the message also to the handlers
656 	// and messengers which were subscribed to ALL events,
657 	// since they aren't caught by the above loops.
658 	// TODO: cleanup
659 	vector<BHandler *> &handlersAll = fHandlerMap[B_OBSERVER_OBSERVE_ALL];
660 	for (uint32 i = 0; i < handlersAll.size(); ++i) {
661 		BMessenger msgr(handlersAll[i]);
662 		msgr.SendMessage(copyMsg);
663 	}
664 
665 	vector<BMessenger> &messengersAll = fMessengerMap[B_OBSERVER_OBSERVE_ALL];
666 	for (uint32 i = 0; i < messengersAll.size(); ++i)
667 		messengers[i].SendMessage(copyMsg);
668 
669 	// Gotta make sure to clean up the annoying temporary ...
670 	delete copyMsg;
671 
672 	return B_OK;
673 }
674 
675 
676 status_t
677 _ObserverList::StartObserving(BHandler *handler, unsigned long what)
678 {
679 	if (handler == NULL)
680 		return B_BAD_HANDLER;
681 
682 	vector<BHandler*> &handlers = fHandlerMap[what];
683 
684 	vector<BHandler*>::iterator iter;
685 	iter = find(handlers.begin(), handlers.end(), handler);
686 	if (iter != handlers.end()) {
687 		// TODO: verify
688 		return B_OK;
689 	}
690 
691 	handlers.push_back(handler);
692 	return B_OK;
693 }
694 
695 
696 status_t
697 _ObserverList::StartObserving(const BMessenger &messenger,
698 	unsigned long what)
699 {
700 	vector<BMessenger> &messengers = fMessengerMap[what];
701 
702 	vector<BMessenger>::iterator iter;
703 	iter = find(messengers.begin(), messengers.end(), messenger);
704 	if (iter != messengers.end()) {
705 		// TODO: verify
706 		return B_OK;
707 	}
708 
709 	messengers.push_back(messenger);
710 	return B_OK;
711 }
712 
713 
714 status_t
715 _ObserverList::StopObserving(BHandler *handler, unsigned long what)
716 {
717 	if (handler == NULL)
718 		return B_BAD_HANDLER;
719 
720 	vector<BHandler*> &handlers = fHandlerMap[what];
721 
722 	vector<BHandler*>::iterator iter;
723 	iter = find(handlers.begin(), handlers.end(), handler);
724 	if (iter != handlers.end()) {
725 		handlers.erase(iter);
726 		if (handlers.empty())
727 			fHandlerMap.erase(what);
728 
729 		return B_OK;
730 	}
731 
732 	return B_BAD_HANDLER;
733 }
734 
735 
736 status_t
737 _ObserverList::StopObserving(const BMessenger &messenger,
738 	unsigned long what)
739 {
740 	// ???:	What if you call StartWatching(MyMsngr, aWhat) and then call
741 	//		StopWatchingAll(MyMsnger)?  Will MyMsnger be removed from the aWhat
742 	//		watcher list?  For now, we'll assume that they're discreet lists
743 	//		which do no cross checking; i.e., MyMsnger would *not* be removed in
744 	//		this scenario.
745 	vector<BMessenger> &messengers = fMessengerMap[what];
746 
747 	vector<BMessenger>::iterator iter;
748 	iter = find(messengers.begin(), messengers.end(), messenger);
749 	if (iter != messengers.end()) {
750 		messengers.erase(iter);
751 		if (messengers.empty())
752 			fMessengerMap.erase(what);
753 
754 		return B_OK;
755 	}
756 
757 	return B_BAD_HANDLER;
758 }
759 
760 
761 bool
762 _ObserverList::IsEmpty()
763 {
764 	return fHandlerMap.empty() && fMessengerMap.empty();
765 }
766 
767 
768 //	#pragma mark -
769 
770 
771 bool
772 FilterDeleter(void *_filter)
773 {
774 	delete static_cast<BMessageFilter *>(_filter);
775 	return false;
776 }
777 
778