2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
12 #include <LaunchRoster.h>
14 #include <ObjectList.h>
16 #include <StringList.h>
19 #include "LaunchDaemon.h"
20 #include "NetworkWatcher.h"
22 #include "VolumeWatcher.h"
25 class EventContainer
: public Event
{
27 EventContainer(Event
* parent
,
28 const BMessenger
* target
,
29 const BMessage
& args
);
30 EventContainer(BaseJob
* owner
,
31 const BMessenger
& target
);
34 void AddEvent(Event
* event
);
35 BObjectList
<Event
>& Events();
37 const BMessenger
& Target() const;
39 virtual status_t
Register(EventRegistrator
& registrator
);
40 virtual void Unregister(EventRegistrator
& registrator
);
42 virtual void Trigger();
44 virtual BaseJob
* Owner() const;
45 virtual void SetOwner(BaseJob
* owner
);
48 void AddEventsToString(BString
& string
) const;
53 BObjectList
<Event
> fEvents
;
58 class OrEvent
: public EventContainer
{
60 OrEvent(Event
* parent
, const BMessenger
* target
,
61 const BMessage
& args
);
62 OrEvent(BaseJob
* owner
,
63 const BMessenger
& target
);
65 virtual void ResetTrigger();
67 virtual BString
ToString() const;
71 class StickyEvent
: public Event
{
73 StickyEvent(Event
* parent
);
74 virtual ~StickyEvent();
76 virtual void ResetSticky();
77 virtual void ResetTrigger();
81 class DemandEvent
: public Event
{
83 DemandEvent(Event
* parent
);
85 virtual status_t
Register(EventRegistrator
& registrator
);
86 virtual void Unregister(EventRegistrator
& registrator
);
88 virtual BString
ToString() const;
92 class ExternalEvent
: public Event
{
94 ExternalEvent(Event
* parent
, const char* name
,
95 const BMessage
& args
);
97 const BString
& Name() const;
98 bool Resolve(uint32 flags
);
101 virtual void ResetTrigger();
103 virtual status_t
Register(EventRegistrator
& registrator
);
104 virtual void Unregister(EventRegistrator
& registrator
);
106 virtual BString
ToString() const;
110 BStringList fArguments
;
116 class FileCreatedEvent
: public Event
{
118 FileCreatedEvent(Event
* parent
,
119 const BMessage
& args
);
121 virtual status_t
Register(EventRegistrator
& registrator
);
122 virtual void Unregister(EventRegistrator
& registrator
);
124 virtual BString
ToString() const;
131 class VolumeMountedEvent
: public Event
, public VolumeListener
{
133 VolumeMountedEvent(Event
* parent
,
134 const BMessage
& args
);
136 virtual status_t
Register(EventRegistrator
& registrator
);
137 virtual void Unregister(EventRegistrator
& registrator
);
139 virtual BString
ToString() const;
141 virtual void VolumeMounted(dev_t device
);
142 virtual void VolumeUnmounted(dev_t device
);
146 class NetworkAvailableEvent
: public StickyEvent
, public NetworkListener
{
148 NetworkAvailableEvent(Event
* parent
,
149 const BMessage
& args
);
151 virtual status_t
Register(EventRegistrator
& registrator
);
152 virtual void Unregister(EventRegistrator
& registrator
);
154 virtual BString
ToString() const;
156 virtual void NetworkAvailabilityChanged(bool available
);
161 create_event(Event
* parent
, const char* name
, const BMessenger
* target
,
162 const BMessage
& args
)
164 if (strcmp(name
, "or") == 0) {
168 return new OrEvent(parent
, target
, args
);
171 if (strcmp(name
, "demand") == 0)
172 return new DemandEvent(parent
);
173 if (strcmp(name
, "file_created") == 0)
174 return new FileCreatedEvent(parent
, args
);
175 if (strcmp(name
, "volume_mounted") == 0)
176 return new VolumeMountedEvent(parent
, args
);
177 if (strcmp(name
, "network_available") == 0)
178 return new NetworkAvailableEvent(parent
, args
);
180 return new ExternalEvent(parent
, name
, args
);
187 Event::Event(Event
* parent
)
201 Event::Triggered() const
217 Event::ResetTrigger()
227 return fParent
->Owner();
234 Event::SetOwner(BaseJob
* owner
)
237 fParent
->SetOwner(owner
);
242 Event::Parent() const
251 EventContainer::EventContainer(Event
* parent
, const BMessenger
* target
,
252 const BMessage
& args
)
264 for (int32 index
= 0; args
.GetInfo(B_MESSAGE_TYPE
, index
, &name
, &type
,
265 &count
) == B_OK
; index
++) {
267 for (int32 messageIndex
= 0; args
.FindMessage(name
, messageIndex
,
268 &message
) == B_OK
; messageIndex
++) {
269 AddEvent(create_event(this, name
, target
, message
));
275 EventContainer::EventContainer(BaseJob
* owner
, const BMessenger
& target
)
287 EventContainer::AddEvent(Event
* event
)
290 fEvents
.AddItem(event
);
295 EventContainer::Events()
302 EventContainer::Target() const
309 EventContainer::Register(EventRegistrator
& registrator
)
314 int32 count
= fEvents
.CountItems();
315 for (int32 index
= 0; index
< count
; index
++) {
316 Event
* event
= fEvents
.ItemAt(index
);
317 status_t status
= event
->Register(registrator
);
328 EventContainer::Unregister(EventRegistrator
& registrator
)
330 int32 count
= fEvents
.CountItems();
331 for (int32 index
= 0; index
< count
; index
++) {
332 Event
* event
= fEvents
.ItemAt(index
);
333 event
->Unregister(registrator
);
339 EventContainer::Trigger()
343 if (Parent() == NULL
&& Owner() != NULL
) {
344 BMessage
message(kMsgEventTriggered
);
345 message
.AddString("owner", Owner()->Name());
346 fTarget
.SendMessage(&message
);
352 EventContainer::Owner() const
359 EventContainer::SetOwner(BaseJob
* owner
)
361 Event::SetOwner(owner
);
367 EventContainer::AddEventsToString(BString
& string
) const
371 for (int32 index
= 0; index
< fEvents
.CountItems(); index
++) {
374 string
+= fEvents
.ItemAt(index
)->ToString();
383 OrEvent::OrEvent(Event
* parent
, const BMessenger
* target
, const BMessage
& args
)
385 EventContainer(parent
, target
, args
)
390 OrEvent::OrEvent(BaseJob
* owner
, const BMessenger
& target
)
392 EventContainer(owner
, target
)
398 OrEvent::ResetTrigger()
402 int32 count
= fEvents
.CountItems();
403 for (int32 index
= 0; index
< count
; index
++) {
404 Event
* event
= fEvents
.ItemAt(index
);
405 event
->ResetTrigger();
406 fTriggered
|= event
->Triggered();
412 OrEvent::ToString() const
414 BString string
= "or ";
415 EventContainer::AddEventsToString(string
);
420 // #pragma mark - StickyEvent
423 StickyEvent::StickyEvent(Event
* parent
)
430 StickyEvent::~StickyEvent()
436 StickyEvent::ResetSticky()
438 Event::ResetTrigger();
443 StickyEvent::ResetTrigger()
445 // This is a sticky event; we don't reset the trigger here
449 // #pragma mark - demand
452 DemandEvent::DemandEvent(Event
* parent
)
460 DemandEvent::Register(EventRegistrator
& registrator
)
467 DemandEvent::Unregister(EventRegistrator
& registrator
)
473 DemandEvent::ToString() const
479 // #pragma mark - External event
482 ExternalEvent::ExternalEvent(Event
* parent
, const char* name
,
483 const BMessage
& args
)
490 const char* argument
;
491 for (int32 index
= 0; args
.FindString("args", index
, &argument
) == B_OK
;
493 fArguments
.Add(argument
);
499 ExternalEvent::Name() const
506 ExternalEvent::Resolve(uint32 flags
)
518 ExternalEvent::ResetSticky()
520 if ((fFlags
& B_STICKY_EVENT
) != 0)
521 Event::ResetTrigger();
526 ExternalEvent::ResetTrigger()
528 if ((fFlags
& B_STICKY_EVENT
) == 0)
529 Event::ResetTrigger();
534 ExternalEvent::Register(EventRegistrator
& registrator
)
536 return registrator
.RegisterExternalEvent(this, Name().String(), fArguments
);
541 ExternalEvent::Unregister(EventRegistrator
& registrator
)
543 registrator
.UnregisterExternalEvent(this, Name().String());
548 ExternalEvent::ToString() const
554 // #pragma mark - file_created
557 FileCreatedEvent::FileCreatedEvent(Event
* parent
, const BMessage
& args
)
561 fPath
.SetTo(args
.GetString("args", NULL
));
566 FileCreatedEvent::Register(EventRegistrator
& registrator
)
574 FileCreatedEvent::Unregister(EventRegistrator
& registrator
)
580 FileCreatedEvent::ToString() const
582 BString string
= "file_created ";
583 string
<< fPath
.Path();
591 VolumeMountedEvent::VolumeMountedEvent(Event
* parent
, const BMessage
& args
)
599 VolumeMountedEvent::Register(EventRegistrator
& registrator
)
601 VolumeWatcher::Register(this);
607 VolumeMountedEvent::Unregister(EventRegistrator
& registrator
)
609 VolumeWatcher::Unregister(this);
614 VolumeMountedEvent::ToString() const
616 return "volume_mounted";
621 VolumeMountedEvent::VolumeMounted(dev_t device
)
628 VolumeMountedEvent::VolumeUnmounted(dev_t device
)
636 NetworkAvailableEvent::NetworkAvailableEvent(Event
* parent
,
637 const BMessage
& args
)
645 NetworkAvailableEvent::Register(EventRegistrator
& registrator
)
647 NetworkWatcher::Register(this);
653 NetworkAvailableEvent::Unregister(EventRegistrator
& registrator
)
655 NetworkWatcher::Unregister(this);
660 NetworkAvailableEvent::ToString() const
662 return "network_available";
667 NetworkAvailableEvent::NetworkAvailabilityChanged(bool available
)
680 Events::FromMessage(const BMessenger
& target
, const BMessage
& message
)
682 return create_event(NULL
, "or", &target
, message
);
687 Events::AddOnDemand(const BMessenger
& target
, Event
* event
)
689 OrEvent
* orEvent
= dynamic_cast<OrEvent
*>(event
);
690 if (orEvent
== NULL
) {
691 EventContainer
* container
= dynamic_cast<EventContainer
*>(event
);
692 if (container
!= NULL
)
693 orEvent
= new OrEvent(container
->Owner(), container
->Target());
695 orEvent
= new OrEvent(NULL
, target
);
697 if (orEvent
!= event
&& event
!= NULL
)
698 orEvent
->AddEvent(event
);
700 orEvent
->AddEvent(new DemandEvent(orEvent
));
706 Events::ResolveExternalEvent(Event
* event
, const char* name
, uint32 flags
)
711 if (EventContainer
* container
= dynamic_cast<EventContainer
*>(event
)) {
712 for (int32 index
= 0; index
< container
->Events().CountItems();
714 Event
* event
= container
->Events().ItemAt(index
);
715 if (ExternalEvent
* external
= dynamic_cast<ExternalEvent
*>(event
)) {
716 if (external
->Name() == name
&& external
->Resolve(flags
))
718 } else if (dynamic_cast<EventContainer
*>(event
) != NULL
) {
719 if (ResolveExternalEvent(event
, name
, flags
))
729 Events::TriggerExternalEvent(Event
* event
, const char* name
)
734 if (EventContainer
* container
= dynamic_cast<EventContainer
*>(event
)) {
735 for (int32 index
= 0; index
< container
->Events().CountItems();
737 Event
* event
= container
->Events().ItemAt(index
);
738 if (ExternalEvent
* external
= dynamic_cast<ExternalEvent
*>(event
)) {
739 if (external
->Name() == name
) {
743 } else if (dynamic_cast<EventContainer
*>(event
) != NULL
) {
744 TriggerExternalEvent(event
, name
);
753 Events::ResetStickyExternalEvent(Event
* event
, const char* name
)
758 if (EventContainer
* container
= dynamic_cast<EventContainer
*>(event
)) {
759 for (int32 index
= 0; index
< container
->Events().CountItems();
761 Event
* event
= container
->Events().ItemAt(index
);
762 if (ExternalEvent
* external
= dynamic_cast<ExternalEvent
*>(event
)) {
763 if (external
->Name() == name
) {
764 external
->ResetSticky();
767 } else if (dynamic_cast<EventContainer
*>(event
) != NULL
) {
768 ResetStickyExternalEvent(event
, name
);
776 /*! This will trigger a demand event, if it exists.
778 \param testOnly If \c true, the deman will not actually be triggered,
779 it will only be checked if it could.
780 \return \c true, if there is a demand event, and it has been
781 triggered by this call. \c false if not.
784 Events::TriggerDemand(Event
* event
, bool testOnly
)
786 if (event
== NULL
|| event
->Triggered())
789 if (EventContainer
* container
= dynamic_cast<EventContainer
*>(event
)) {
790 for (int32 index
= 0; index
< container
->Events().CountItems();
792 Event
* childEvent
= container
->Events().ItemAt(index
);
793 if (dynamic_cast<DemandEvent
*>(childEvent
) != NULL
) {
797 childEvent
->Trigger();
800 if (dynamic_cast<EventContainer
*>(childEvent
) != NULL
) {
801 if (TriggerDemand(childEvent
, testOnly
))
807 return event
->Triggered();