New test.
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / Project.cs
1 //
2 // Project.cs: Project class
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 #if NET_2_0
29
30 using System;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Collections.Specialized;
34 using System.IO;
35 using System.Text;
36 using System.Xml;
37 using System.Xml.Schema;
38 using Microsoft.Build.Framework;
39 using Mono.XBuild.Framework;
40
41 namespace Microsoft.Build.BuildEngine {
42         public class Project {
43         
44                 bool                            buildEnabled;
45                 //IDictionary                   conditionedProperties;
46                 Dictionary <string, List <string>>      conditionedProperties;
47                 string[]                        defaultTargets;
48                 Encoding                        encoding;
49                 BuildItemGroup                  evaluatedItems;
50                 BuildItemGroup                  evaluatedItemsIgnoringCondition;
51                 Dictionary <string, BuildItemGroup>     evaluatedItemsByName;
52                 Dictionary <string, BuildItemGroup>     evaluatedItemsByNameIgnoringCondition;
53                 BuildPropertyGroup              evaluatedProperties;
54                 string                          firstTargetName;
55                 string                          fullFileName;
56                 BuildPropertyGroup              globalProperties;
57                 GroupingCollection              groups;
58                 bool                            isDirty;
59                 bool                            isValidated;
60                 BuildItemGroupCollection        itemGroups;
61                 ImportCollection                imports;
62                 string                          initialTargets;
63                 Engine                          parentEngine;
64                 BuildPropertyGroupCollection    propertyGroups;
65                 string                          schemaFile;
66                 TaskDatabase                    taskDatabase;
67                 TargetCollection                targets;
68                 DateTime                        timeOfLastDirty;
69                 UsingTaskCollection             usingTasks;
70                 XmlDocument                     xmlDocument;
71                 bool                            unloaded;
72
73                 public Project ()
74                         : this (Engine.GlobalEngine)
75                 {
76                 }
77
78                 public Project (Engine engine)
79                 {
80                         parentEngine  = engine;
81                         xmlDocument = new XmlDocument ();
82                         groups = new GroupingCollection ();
83                         imports = new ImportCollection (this);
84                         usingTasks = new UsingTaskCollection (this);
85                         itemGroups = new BuildItemGroupCollection (groups);
86                         propertyGroups = new BuildPropertyGroupCollection (groups);
87                         targets = new TargetCollection (this);
88                         
89                         taskDatabase = new TaskDatabase ();
90                         if (engine.DefaultTasksRegistered == true)
91                                 taskDatabase.CopyTasks (engine.DefaultTasks);
92                         
93                         globalProperties = new BuildPropertyGroup ();
94                         fullFileName = String.Empty;
95
96                         foreach (BuildProperty bp in parentEngine.GlobalProperties) {
97                                 GlobalProperties.AddProperty (bp.Clone (true));
98                         }
99
100                         // You can evaluate an empty project.
101                         Evaluate ();
102                 }
103
104                 [MonoTODO]
105                 public void AddNewImport (string importLocation,
106                                           string importCondition)
107                 {
108                         throw new NotImplementedException ();
109                 }
110
111                 [MonoTODO]
112                 public BuildItem AddNewItem (string itemName,
113                                              string itemInclude)
114                 {
115                         return AddNewItem (itemName, itemInclude, false);
116                 }
117                 
118                 [MonoTODO]
119                 public BuildItem AddNewItem (string itemName,
120                                              string itemInclude,
121                                              bool treatItemIncludeAsLiteral)
122                 {
123                         throw new NotImplementedException ();
124                 }
125
126                 [MonoTODO]
127                 public BuildItemGroup AddNewItemGroup ()
128                 {
129                         throw new NotImplementedException ();
130                 }
131
132                 [MonoTODO]
133                 public BuildPropertyGroup AddNewPropertyGroup (bool insertAtEndOfProject)
134                 {
135                         throw new NotImplementedException ();
136                 }
137                 
138                 [MonoTODO]
139                 public void AddNewUsingTaskFromAssemblyFile (string taskName,
140                                                              string assemblyFile)
141                 {
142                         throw new NotImplementedException ();
143                 }
144                 
145                 [MonoTODO]
146                 public void AddNewUsingTaskFromAssemblyName (string taskName,
147                                                              string assemblyName)
148                 {
149                         throw new NotImplementedException ();
150                 }
151                 
152                 [MonoTODO]
153                 public bool Build ()
154                 {
155                         return true;
156                 }
157                 
158                 [MonoTODO]
159                 public bool Build (string targetName)
160                 {
161                         if (targets.Exists (targetName) == false)
162                                 throw new Exception ("Target specified to build does not exist.");
163                         
164                         return this.targets [targetName].Build ();
165                 }
166                 
167                 [MonoTODO]
168                 public bool Build (string[] targetNames)
169                 {
170                         return Build (targetNames, new Hashtable ());
171                 }
172                 
173                 [MonoTODO]
174                 public bool Build (string[] targetNames,
175                                    IDictionary targetOutputs)
176                 {
177                         return Build (targetNames, new Hashtable (), BuildSettings.None);
178                 }
179                 
180                 [MonoTODO]
181                 public bool Build (string[] targetNames,
182                                    IDictionary targetOutputs,
183                                    BuildSettings buildFlags)
184                 
185                 {
186                         CheckUnloaded ();
187                         if (targetNames.Length == 0) {
188                                 if (defaultTargets.Length != 0) {
189                                         targetNames = defaultTargets;
190                                 }
191                                 else if (firstTargetName != null) {
192                                         targetNames = new string [1] { firstTargetName};
193                                 }
194                                 else
195                                         return false;
196                         }
197                         foreach (string target in targetNames) {
198                                 if (Build (target) == false) {
199                                         return false;
200                                 }
201                         }
202                         return true;
203                 }
204
205                 [MonoTODO]
206                 public string[] GetConditionedPropertyValues (string propertyName)
207                 {
208                         if (conditionedProperties.ContainsKey (propertyName))
209                                 return conditionedProperties [propertyName].ToArray ();
210                         else
211                                 return new string [0];
212                 }
213
214                 public BuildItemGroup GetEvaluatedItemsByName (string itemName)
215                 {
216                         if (evaluatedItemsByName.ContainsKey (itemName))
217                                 return evaluatedItemsByName [itemName];
218                         else
219                                 return null;
220                 }
221
222                 public BuildItemGroup GetEvaluatedItemsByNameIgnoringCondition (string itemName)
223                 {
224                         if (evaluatedItemsByNameIgnoringCondition.ContainsKey (itemName))
225                                 return evaluatedItemsByNameIgnoringCondition [itemName];
226                         else
227                                 return null;
228                 }
229
230                 public string GetEvaluatedProperty (string propertyName)
231                 {
232                         return (string) evaluatedProperties [propertyName];
233                 }
234
235                 [MonoTODO]
236                 public string GetProjectExtensions (string id)
237                 {
238                         throw new NotImplementedException ();
239                 }
240
241                 // Does the actual loading.
242                 private void DoLoad (TextReader textReader)
243                 {
244                         ParentEngine.RemoveLoadedProject (this);
245
246                         XmlReaderSettings settings = new XmlReaderSettings ();
247
248                         if (SchemaFile != null) {
249                                 settings.Schemas.Add (null, SchemaFile);
250                                 settings.ValidationType = ValidationType.Schema;
251                                 settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
252                         }
253
254                         XmlReader xmlReader = XmlReader.Create (textReader, settings);
255                         xmlDocument.Load (xmlReader);
256
257                         if (xmlDocument.DocumentElement.GetAttribute ("xmlns") != "http://schemas.microsoft.com/developer/msbuild/2003") {
258                                 throw new InvalidProjectFileException (
259                                         @"The default XML namespace of the project must be the MSBuild XML namespace." + 
260                                         " If the project is authored in the MSBuild 2003 format, please add " +
261                                         "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" to the <Project> element. " +
262                                         "If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format.  ");
263                         }
264                         ProcessXml ();
265                         ParentEngine.AddLoadedProject (this);
266                 }
267
268                 public void Load (string projectFileName)
269                 {
270                         this.fullFileName = Path.GetFullPath (projectFileName);
271                         DoLoad (new StreamReader (projectFileName));
272                 }
273                 
274                 [MonoTODO]
275                 public void Load (TextReader textReader)
276                 {
277                         fullFileName = String.Empty;
278                         DoLoad (textReader);
279                 }
280
281                 public void LoadXml (string projectXml)
282                 {
283                         fullFileName = String.Empty;
284                         DoLoad (new StringReader (projectXml));
285                 }
286
287                 internal void Unload ()
288                 {
289                         unloaded = true;
290                 }
291
292                 internal void CheckUnloaded ()
293                 {
294                         if (unloaded)
295                                 throw new InvalidOperationException ("This project object is no longer valid.");
296                 }
297
298                 private void ProcessXml ()
299                 {
300                         XmlElement xmlElement = xmlDocument.DocumentElement;
301                         if (xmlElement.Name != "Project")
302                                 throw new InvalidProjectFileException ("Invalid root element.");
303                         if (xmlElement.GetAttributeNode ("DefaultTargets") != null)
304                                 defaultTargets = xmlElement.GetAttribute ("DefaultTargets").Split (';');
305                         else
306                                 defaultTargets = new string [0];
307                         
308                         ProcessElements (xmlElement, null);
309                         
310                         isDirty = false;
311                         Evaluate ();
312                 }
313
314                 private void InitializeProperties ()
315                 {
316                         BuildProperty bp;
317
318                         foreach (BuildProperty gp in GlobalProperties) {
319                                 bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
320                                 EvaluatedProperties.AddProperty (bp);
321                         }
322                         
323                         foreach (DictionaryEntry de in Environment.GetEnvironmentVariables ()) {
324                                 bp = new BuildProperty ((string) de.Key, (string) de.Value, PropertyType.Environment);
325                                 EvaluatedProperties.AddProperty (bp);
326                         }
327
328                         bp = new BuildProperty ("MSBuildBinPath", parentEngine.BinPath, PropertyType.Reserved);
329                         EvaluatedProperties.AddProperty (bp);
330                 }
331
332                 internal void Evaluate ()
333                 {
334                         evaluatedItems = new BuildItemGroup (null, this);
335                         evaluatedItemsIgnoringCondition = new BuildItemGroup (null, this);
336                         evaluatedItemsByName = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
337                         evaluatedItemsByNameIgnoringCondition = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
338                         evaluatedProperties = new BuildPropertyGroup ();
339
340                         InitializeProperties ();
341
342                         // FIXME: questionable order of evaluation
343                         
344                         foreach (Import import in Imports)
345                                 import.Evaluate ();
346                         
347                         foreach (BuildPropertyGroup bpg in PropertyGroups) {
348                                 if (bpg.Condition == String.Empty)
349                                         bpg.Evaluate ();
350                                 else {
351                                         ConditionExpression ce = ConditionParser.ParseCondition (bpg.Condition);
352                                         if (ce.BoolEvaluate (this))
353                                                 bpg.Evaluate ();
354                                 }
355                         }
356                         
357                         foreach (BuildItemGroup big in ItemGroups) {
358                                 if (big.Condition == String.Empty)
359                                         big.Evaluate ();
360                                 else {
361                                         ConditionExpression ce = ConditionParser.ParseCondition (big.Condition);
362                                         if (ce.BoolEvaluate (this))
363                                                 big.Evaluate ();
364                                 }
365                         }
366                         
367                         foreach (UsingTask usingTask in UsingTasks)
368                                 usingTask.Evaluate ();
369                 }
370
371                 public void MarkProjectAsDirty ()
372                 {
373                         isDirty = true;
374                 }
375
376                 [MonoTODO]
377                 public void RemoveAllItemGroups ()
378                 {
379                         throw new NotImplementedException ();
380                 }
381
382                 [MonoTODO]
383                 public void RemoveAllPropertyGroups ()
384                 {
385                         throw new NotImplementedException ();
386                 }
387
388                 [MonoTODO]
389                 public void RemoveItem (BuildItem itemToRemove)
390                 {
391                         throw new NotImplementedException ();
392                 }
393
394                 [MonoTODO]
395                 public void RemoveItemGroup (BuildItemGroup itemGroupToRemove)
396                 {
397                         throw new NotImplementedException ();
398                 }
399                 
400                 [MonoTODO]
401                 // NOTE: does not modify imported projects
402                 public void RemoveItemGroupsWithMatchingCondition (string matchingCondition)
403                 {
404                         throw new NotImplementedException ();
405                 }
406
407                 [MonoTODO]
408                 public void RemoveItemsByName (string itemName)
409                 {
410                         throw new NotImplementedException ();
411                 }
412
413                 [MonoTODO]
414                 public void RemovePropertyGroup (BuildPropertyGroup propertyGroupToRemove)
415                 {
416                         throw new NotImplementedException ();
417                 }
418                 
419                 [MonoTODO]
420                 // NOTE: does not modify imported projects
421                 public void RemovePropertyGroupsWithMatchingCondition (string matchCondition)
422                 {
423                         throw new NotImplementedException ();
424                 }
425
426                 [MonoTODO]
427                 public void ResetBuildStatus ()
428                 {
429                         throw new NotImplementedException ();
430                 }
431
432                 public void Save (string projectFileName)
433                 {
434                         Save (projectFileName, Encoding.Default);
435                 }
436
437                 public void Save (string projectFileName, Encoding encoding)
438                 {
439                         xmlDocument.Save (projectFileName);
440                 }
441
442                 public void Save (TextWriter outTextWriter)
443                 {
444                         xmlDocument.Save (outTextWriter);
445                 }
446
447                 [MonoTODO]
448                 public void SetImportedProperty (string propertyName,
449                                                  string propertyValue,
450                                                  string condition,
451                                                  Project importProject)
452                 {
453                         SetImportedProperty (propertyName, propertyValue, condition, importProject,
454                                 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
455                 }
456
457                 [MonoTODO]
458                 public void SetImportedProperty (string propertyName,
459                                                  string propertyValue,
460                                                  string condition,
461                                                  Project importedProject,
462                                                  PropertyPosition position)
463                 {
464                         SetImportedProperty (propertyName, propertyValue, condition, importedProject,
465                                 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
466                 }
467
468                 [MonoTODO]
469                 public void SetImportedProperty (string propertyName,
470                                                  string propertyValue,
471                                                  string condition,
472                                                  Project importedProject,
473                                                  PropertyPosition position,
474                                                  bool treatPropertyValueAsLiteral)
475                 {
476                         throw new NotImplementedException ();
477                 }
478
479                 [MonoTODO]
480                 public void SetProjectExtensions (string id, string xmlText)
481                 {
482                         throw new NotImplementedException ();
483                 }
484                 
485                 [MonoTODO]
486                 public void SetProperty (string propertyName,
487                                          string propertyValue)
488                 {
489                         SetProperty (propertyName, propertyValue, "true",
490                                 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
491                 }
492
493                 [MonoTODO]
494                 public void SetProperty (string propertyName,
495                                          string propertyValue,
496                                          string condition)
497                 {
498                         SetProperty (propertyName, propertyValue, condition,
499                                 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
500                 }
501
502                 [MonoTODO]
503                 public void SetProperty (string propertyName,
504                                          string propertyValue,
505                                          string condition,
506                                          PropertyPosition position)
507                 {
508                         SetProperty (propertyName, propertyValue, condition,
509                                 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
510                 }
511
512                 [MonoTODO]
513                 public void SetProperty (string propertyName,
514                                          string propertyValue,
515                                          string condition,
516                                          PropertyPosition position,
517                                          bool treatPropertyValueAsLiteral)
518                 {
519                         throw new NotImplementedException ();
520                 }
521
522                 internal void ProcessElements (XmlElement rootElement, ImportedProject ip)
523                 {
524                         foreach (XmlNode xn in rootElement.ChildNodes) {
525                                 if (xn is XmlElement) {
526                                         XmlElement xe = (XmlElement) xn;
527                                         switch (xe.Name) {
528                                         case "ProjectExtensions":
529                                                 AddProjectExtensions (xe);
530                                                 break;
531                                         case "Warning":
532                                         case "Message":
533                                         case "Error":
534                                                 AddMessage (xe);
535                                                 break;
536                                         case "Target":
537                                                 AddTarget (xe, ip);
538                                                 break;
539                                         case "UsingTask":
540                                                 AddUsingTask (xe, ip);
541                                                 break;
542                                         case "Import":
543                                                 AddImport (xe, ip);
544                                                 break;
545                                         case "ItemGroup":
546                                                 AddItemGroup (xe);
547                                                 break;
548                                         case "PropertyGroup":
549                                                 AddPropertyGroup (xe);
550                                                 break;
551                                         case  "Choose":
552                                                 AddChoose (xe);
553                                                 break;
554                                         default:
555                                                 throw new InvalidProjectFileException ("Invalid element in project file.");
556                                         }
557                                 }
558                         }
559                 }
560                 
561                 private void AddProjectExtensions (XmlElement xmlElement)
562                 {
563                         if (xmlElement == null)
564                                 throw new ArgumentNullException ("xmlElement");
565                 }
566                 
567                 private void AddMessage (XmlElement xmlElement)
568                 {
569                         if (xmlElement == null)
570                                 throw new ArgumentNullException ("xmlElement");
571                 }
572                 
573                 private void AddTarget (XmlElement xmlElement, ImportedProject importedProject)
574                 {
575                         if (xmlElement == null)
576                                 throw new ArgumentNullException ("xmlElement");
577                         Target target = new Target (xmlElement, this);
578                         targets.AddTarget (target);
579                         if (importedProject == null) {
580                                 target.IsImported = false;
581                                 if (firstTargetName == null)
582                                         firstTargetName = target.Name;
583                         } else
584                                 target.IsImported = true;
585                 }
586                 
587                 private void AddUsingTask (XmlElement xmlElement, ImportedProject importedProject)
588                 {
589                         UsingTask usingTask;
590
591                         usingTask = new UsingTask (xmlElement, this, importedProject);
592                         UsingTasks.Add (usingTask);
593                 }
594                 
595                 private void AddImport (XmlElement xmlElement, ImportedProject importingProject)
596                 {
597                         Import import;
598                         
599                         import = new Import (xmlElement, this, importingProject);
600                         Imports.Add (import);
601                 }
602                 
603                 private void AddItemGroup (XmlElement xmlElement)
604                 {
605                         if (xmlElement == null)
606                                 throw new ArgumentNullException ("xmlElement");
607                         BuildItemGroup big = new BuildItemGroup (xmlElement, this);
608                         ItemGroups.Add (big);
609                         //big.Evaluate ();
610                 }
611                 
612                 private void AddPropertyGroup (XmlElement xmlElement)
613                 {
614                         if (xmlElement == null)
615                                 throw new ArgumentNullException ("xmlElement");
616                         BuildPropertyGroup bpg = new BuildPropertyGroup (xmlElement, this);
617                         PropertyGroups.Add (bpg);
618                         //bpg.Evaluate ();
619                 }
620                 
621                 private void AddChoose (XmlElement xmlElement)
622                 {
623                         if (xmlElement == null)
624                                 throw new ArgumentNullException ("xmlElement");
625                                 
626                         BuildChoose bc = new BuildChoose (xmlElement, this);
627                         groups.Add (bc);
628                         
629                 }
630                 
631                 private static void ValidationCallBack (object sender, ValidationEventArgs e)
632                 {
633                         Console.WriteLine ("Validation Error: {0}", e.Message);
634                 }
635                 
636                 public bool BuildEnabled {
637                         get {
638                                 return buildEnabled;
639                         }
640                         set {
641                                 buildEnabled = value;
642                         }
643                 }
644
645                 public Encoding Encoding {
646                         get { return encoding; }
647                 }
648
649                 public string DefaultTargets {
650                         get {
651                                 return xmlDocument.DocumentElement.GetAttribute ("DefaultTargets");
652                         }
653                         set {
654                                 xmlDocument.DocumentElement.SetAttribute ("DefaultTargets", value);
655                                 defaultTargets = value.Split (';');
656                         }
657                 }
658
659                 public BuildItemGroup EvaluatedItems {
660                         get { return evaluatedItems; }
661                 }
662
663                 public BuildItemGroup EvaluatedItemsIgnoringCondition {
664                         get { return evaluatedItemsIgnoringCondition; }
665                 }
666                 
667                 internal IDictionary EvaluatedItemsByName {
668                         get { return evaluatedItemsByName; }
669                 }
670                 
671                 internal IDictionary EvaluatedItemsByNameIgnoringCondition {
672                         get { return evaluatedItemsByNameIgnoringCondition; }
673                 }
674
675                 public BuildPropertyGroup EvaluatedProperties {
676                         get { return evaluatedProperties; }
677                 }
678
679                 public string FullFileName {
680                         get { return fullFileName; }
681                         set { fullFileName = value; }
682                 }
683
684                 public BuildPropertyGroup GlobalProperties {
685                         get { return globalProperties; }
686                         set {
687                                 if (value == null) {
688                                         throw new ArgumentNullException ("value");
689                                 }
690                                 if (value.FromXml) {
691                                         throw new InvalidOperationException ("Can't do that.");
692                                 }
693                                 globalProperties = value;
694                         }
695                 }
696
697                 public bool IsDirty {
698                         get { return isDirty; }
699                 }
700
701                 public bool IsValidated {
702                         get { return isValidated; }
703                         set { isValidated = value; }
704                 }
705
706                 public BuildItemGroupCollection ItemGroups {
707                         get { return itemGroups; }
708                 }
709                 
710                 public ImportCollection Imports {
711                         get { return imports; }
712                 }
713                 
714                 public string InitialTargets {
715                         get { return initialTargets; }
716                         set { initialTargets = value; }
717                 }
718
719                 public Engine ParentEngine {
720                         get { return parentEngine; }
721                 }
722
723                 public BuildPropertyGroupCollection PropertyGroups {
724                         get { return propertyGroups; }
725                 }
726
727                 public string SchemaFile {
728                         get { return schemaFile; }
729                         set { schemaFile = value; }
730                 }
731
732                 public TargetCollection Targets {
733                         get { return targets; }
734                 }
735
736                 public DateTime TimeOfLastDirty {
737                         get { return timeOfLastDirty; }
738                 }
739                 
740                 public UsingTaskCollection UsingTasks {
741                         get { return usingTasks; }
742                 }
743
744                 [MonoTODO]
745                 public string Xml {
746                         get { return xmlDocument.InnerXml; }
747                 }
748                 
749                 internal TaskDatabase TaskDatabase {
750                         get { return taskDatabase; }
751                 }
752         }
753 }
754
755 #endif