docs/ikteam: Delete most files.
[haiku.git] / src / servers / launch / Conditions.cpp
blobe879d06c11f9535ced6d6d9bbe39769ddd54bb67
1 /*
2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "Conditions.h"
9 #include <stdio.h>
11 #include <Entry.h>
12 #include <File.h>
13 #include <ObjectList.h>
14 #include <Message.h>
15 #include <Path.h>
16 #include <StringList.h>
18 #include "NetworkWatcher.h"
19 #include "Utility.h"
22 class ConditionContainer : public Condition {
23 protected:
24 ConditionContainer(const BMessage& args);
25 ConditionContainer();
27 public:
28 void AddCondition(Condition* condition);
30 virtual bool IsConstant(ConditionContext& context) const;
32 protected:
33 void AddConditionsToString(BString& string) const;
35 protected:
36 BObjectList<Condition> fConditions;
40 class AndCondition : public ConditionContainer {
41 public:
42 AndCondition(const BMessage& args);
43 AndCondition();
45 virtual bool Test(ConditionContext& context) const;
46 virtual BString ToString() const;
50 class OrCondition : public ConditionContainer {
51 public:
52 OrCondition(const BMessage& args);
54 virtual bool Test(ConditionContext& context) const;
55 virtual bool IsConstant(ConditionContext& context) const;
57 virtual BString ToString() const;
61 class NotCondition : public ConditionContainer {
62 public:
63 NotCondition(const BMessage& args);
64 NotCondition();
66 virtual bool Test(ConditionContext& context) const;
67 virtual BString ToString() const;
71 class SafeModeCondition : public Condition {
72 public:
73 virtual bool Test(ConditionContext& context) const;
74 virtual bool IsConstant(ConditionContext& context) const;
76 virtual BString ToString() const;
80 class ReadOnlyCondition : public Condition {
81 public:
82 ReadOnlyCondition(const BMessage& args);
84 virtual bool Test(ConditionContext& context) const;
85 virtual bool IsConstant(ConditionContext& context) const;
87 virtual BString ToString() const;
89 private:
90 BString fPath;
91 mutable bool fIsReadOnly;
92 mutable bool fTestPerformed;
96 class FileExistsCondition : public Condition {
97 public:
98 FileExistsCondition(const BMessage& args);
100 virtual bool Test(ConditionContext& context) const;
101 virtual BString ToString() const;
103 private:
104 BStringList fPaths;
108 class NetworkAvailableCondition : public Condition {
109 public:
110 virtual bool Test(ConditionContext& context) const;
111 virtual bool IsConstant(ConditionContext& context) const;
113 virtual BString ToString() const;
117 class SettingCondition : public Condition {
118 public:
119 SettingCondition(const BMessage& args);
121 virtual bool Test(ConditionContext& context) const;
123 virtual BString ToString() const;
125 private:
126 BPath fPath;
127 BString fField;
128 BString fValue;
132 static Condition*
133 create_condition(const char* name, const BMessage& args)
135 if (strcmp(name, "and") == 0 && !args.IsEmpty())
136 return new AndCondition(args);
137 if (strcmp(name, "or") == 0 && !args.IsEmpty())
138 return new OrCondition(args);
139 if (strcmp(name, "not") == 0 && !args.IsEmpty())
140 return new NotCondition(args);
142 if (strcmp(name, "safemode") == 0)
143 return new SafeModeCondition();
144 if (strcmp(name, "read_only") == 0)
145 return new ReadOnlyCondition(args);
146 if (strcmp(name, "file_exists") == 0)
147 return new FileExistsCondition(args);
148 if (strcmp(name, "network_available") == 0)
149 return new NetworkAvailableCondition();
150 if (strcmp(name, "setting") == 0)
151 return new SettingCondition(args);
153 return NULL;
157 // #pragma mark -
160 Condition::Condition()
165 Condition::~Condition()
170 bool
171 Condition::IsConstant(ConditionContext& context) const
173 return false;
177 // #pragma mark -
180 ConditionContainer::ConditionContainer(const BMessage& args)
182 fConditions(10, true)
184 char* name;
185 type_code type;
186 int32 count;
187 for (int32 index = 0; args.GetInfo(B_MESSAGE_TYPE, index, &name, &type,
188 &count) == B_OK; index++) {
189 BMessage message;
190 for (int32 messageIndex = 0; args.FindMessage(name, messageIndex,
191 &message) == B_OK; messageIndex++) {
192 AddCondition(create_condition(name, message));
198 ConditionContainer::ConditionContainer()
200 fConditions(10, true)
205 void
206 ConditionContainer::AddCondition(Condition* condition)
208 if (condition != NULL)
209 fConditions.AddItem(condition);
213 /*! A single constant failing condition makes this constant, too, otherwise,
214 a single non-constant condition makes this non-constant as well.
216 bool
217 ConditionContainer::IsConstant(ConditionContext& context) const
219 bool fixed = true;
220 for (int32 index = 0; index < fConditions.CountItems(); index++) {
221 const Condition* condition = fConditions.ItemAt(index);
222 if (condition->IsConstant(context)) {
223 if (!condition->Test(context))
224 return true;
225 } else
226 fixed = false;
228 return fixed;
232 void
233 ConditionContainer::AddConditionsToString(BString& string) const
235 string += "[";
237 for (int32 index = 0; index < fConditions.CountItems(); index++) {
238 if (index != 0)
239 string += ", ";
240 string += fConditions.ItemAt(index)->ToString();
242 string += "]";
246 // #pragma mark - and
249 AndCondition::AndCondition(const BMessage& args)
251 ConditionContainer(args)
256 AndCondition::AndCondition()
261 bool
262 AndCondition::Test(ConditionContext& context) const
264 for (int32 index = 0; index < fConditions.CountItems(); index++) {
265 Condition* condition = fConditions.ItemAt(index);
266 if (!condition->Test(context))
267 return false;
269 return true;
273 BString
274 AndCondition::ToString() const
276 BString string = "and ";
277 ConditionContainer::AddConditionsToString(string);
278 return string;
282 // #pragma mark - or
285 OrCondition::OrCondition(const BMessage& args)
287 ConditionContainer(args)
292 bool
293 OrCondition::Test(ConditionContext& context) const
295 if (fConditions.IsEmpty())
296 return true;
298 for (int32 index = 0; index < fConditions.CountItems(); index++) {
299 Condition* condition = fConditions.ItemAt(index);
300 if (condition->Test(context))
301 return true;
303 return false;
307 /*! If there is a single succeeding constant condition, this is constant, too.
308 Otherwise, it is non-constant if there is a single non-constant condition.
310 bool
311 OrCondition::IsConstant(ConditionContext& context) const
313 bool fixed = true;
314 for (int32 index = 0; index < fConditions.CountItems(); index++) {
315 const Condition* condition = fConditions.ItemAt(index);
316 if (condition->IsConstant(context)) {
317 if (condition->Test(context))
318 return true;
319 } else
320 fixed = false;
322 return fixed;
326 BString
327 OrCondition::ToString() const
329 BString string = "or ";
330 ConditionContainer::AddConditionsToString(string);
331 return string;
335 // #pragma mark - or
338 NotCondition::NotCondition(const BMessage& args)
340 ConditionContainer(args)
345 NotCondition::NotCondition()
350 bool
351 NotCondition::Test(ConditionContext& context) const
353 for (int32 index = 0; index < fConditions.CountItems(); index++) {
354 Condition* condition = fConditions.ItemAt(index);
355 if (condition->Test(context))
356 return false;
358 return true;
362 BString
363 NotCondition::ToString() const
365 BString string = "not ";
366 ConditionContainer::AddConditionsToString(string);
367 return string;
371 // #pragma mark - safemode
374 bool
375 SafeModeCondition::Test(ConditionContext& context) const
377 return context.IsSafeMode();
381 bool
382 SafeModeCondition::IsConstant(ConditionContext& context) const
384 return true;
388 BString
389 SafeModeCondition::ToString() const
391 return "safemode";
395 // #pragma mark - read_only
398 ReadOnlyCondition::ReadOnlyCondition(const BMessage& args)
400 fPath(args.GetString("args")),
401 fIsReadOnly(false),
402 fTestPerformed(false)
407 bool
408 ReadOnlyCondition::Test(ConditionContext& context) const
410 if (fTestPerformed)
411 return fIsReadOnly;
413 if (fPath.IsEmpty() || fPath == "/boot")
414 fIsReadOnly = context.BootVolumeIsReadOnly();
415 else
416 fIsReadOnly = Utility::IsReadOnlyVolume(fPath);
418 fTestPerformed = true;
420 return fIsReadOnly;
424 bool
425 ReadOnlyCondition::IsConstant(ConditionContext& context) const
427 return true;
431 BString
432 ReadOnlyCondition::ToString() const
434 BString string = "readonly ";
435 string << fPath;
436 return string;
440 // #pragma mark - file_exists
443 FileExistsCondition::FileExistsCondition(const BMessage& args)
445 for (int32 index = 0;
446 const char* path = args.GetString("args", index, NULL); index++) {
447 fPaths.Add(Utility::TranslatePath(path));
452 bool
453 FileExistsCondition::Test(ConditionContext& context) const
455 for (int32 index = 0; index < fPaths.CountStrings(); index++) {
456 BEntry entry;
457 if (entry.SetTo(fPaths.StringAt(index)) != B_OK
458 || !entry.Exists())
459 return false;
461 return true;
465 BString
466 FileExistsCondition::ToString() const
468 BString string = "file_exists [";
469 for (int32 index = 0; index < fPaths.CountStrings(); index++) {
470 if (index != 0)
471 string << ", ";
472 string << fPaths.StringAt(index);
474 string += "]";
475 return string;
479 // #pragma mark - network_available
482 bool
483 NetworkAvailableCondition::Test(ConditionContext& context) const
485 return NetworkWatcher::NetworkAvailable(false);
489 bool
490 NetworkAvailableCondition::IsConstant(ConditionContext& context) const
492 return false;
496 BString
497 NetworkAvailableCondition::ToString() const
499 return "network_available";
503 // #pragma mark - setting
506 SettingCondition::SettingCondition(const BMessage& args)
508 fPath.SetTo(Utility::TranslatePath(args.GetString("args", 0, NULL)));
509 fField = args.GetString("args", 1, NULL);
510 fValue = args.GetString("args", 2, NULL);
514 bool
515 SettingCondition::Test(ConditionContext& context) const
517 BFile file(fPath.Path(), B_READ_ONLY);
518 if (file.InitCheck() != B_OK)
519 return false;
521 BMessage settings;
522 if (settings.Unflatten(&file) == B_OK) {
523 type_code type;
524 int32 count;
525 if (settings.GetInfo(fField, &type, &count) == B_OK) {
526 switch (type) {
527 case B_BOOL_TYPE:
529 bool value = settings.GetBool(fField);
530 bool expect = fValue.IsEmpty();
531 if (!expect) {
532 expect = fValue == "true" || fValue == "yes"
533 || fValue == "on" || fValue == "1";
535 return value == expect;
537 case B_STRING_TYPE:
539 BString value = settings.GetString(fField);
540 if (fValue.IsEmpty() && !value.IsEmpty())
541 return true;
543 return fValue == value;
548 // TODO: check for driver settings, too?
550 return false;
554 BString
555 SettingCondition::ToString() const
557 BString string = "setting file ";
558 string << fPath.Path() << ", field " << fField;
559 if (!fValue.IsEmpty())
560 string << ", value " << fValue;
562 return string;
566 // #pragma mark -
569 /*static*/ Condition*
570 Conditions::FromMessage(const BMessage& message)
572 return create_condition("and", message);
576 /*static*/ Condition*
577 Conditions::AddNotSafeMode(Condition* condition)
579 AndCondition* andCondition = dynamic_cast<AndCondition*>(condition);
580 if (andCondition == NULL)
581 andCondition = new AndCondition();
582 if (andCondition != condition && condition != NULL)
583 andCondition->AddCondition(condition);
585 NotCondition* notCondition = new NotCondition();
586 notCondition->AddCondition(new SafeModeCondition());
588 andCondition->AddCondition(notCondition);
589 return andCondition;