Merge pull request #2698 from esdrubal/iosxmlarray
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Execution / BuildManager.cs
1 // BuildManager.cs
2 //
3 // Author:
4 //   Rolf Bjarne Kvinge (rolf@xamarin.com)
5 //   Atsushi Enomoto (atsushi@xamarin.com)
6 //
7 // Copyright (C) 2011,2013 Xamarin Inc.
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
29 using Microsoft.Build.Evaluation;
30 using System;
31 using System.Collections.Generic;
32 using System.Threading;
33 using Microsoft.Build.Internal;
34 using System.Linq;
35
36 namespace Microsoft.Build.Execution
37 {
38         public class BuildManager
39         {
40                 static BuildManager default_manager = new BuildManager ();
41
42                 public static BuildManager DefaultBuildManager {
43                         get { return default_manager; }
44                 }
45                 
46                 public BuildManager ()
47                 {
48                 }
49
50                 public BuildManager (string hostName)
51                 {
52                         throw new NotImplementedException ();
53                 }
54                 
55                 public void Dispose ()
56                 {
57                         if (submissions.Count > 0)
58                                 WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
59                         BuildNodeManager.Stop ();
60                 }
61
62                 ~BuildManager ()
63                 {
64                         // maybe processes created by out-of-process nodes should be signaled.
65                 }
66
67                 readonly List<BuildSubmission> submissions = new List<BuildSubmission> ();
68                 
69                 BuildParameters ongoing_build_parameters;
70                 
71                 internal BuildParameters OngoingBuildParameters {
72                         get { return ongoing_build_parameters; }
73                 }
74
75                 public void BeginBuild (BuildParameters parameters)
76                 {
77                         if (ongoing_build_parameters != null)
78                                 throw new InvalidOperationException ("There is already ongoing build");
79                         ongoing_build_parameters = parameters.Clone ();
80                 }
81
82                 public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
83                 {
84                         BeginBuild (parameters);
85                         var ret = BuildRequest (requestData);
86                         EndBuild ();
87                         return ret;
88                 }
89
90                 public BuildResult BuildRequest (BuildRequestData requestData)
91                 {
92                         var sub = PendBuildRequest (requestData);
93                         sub.Execute ();
94                         return sub.BuildResult;
95                 }
96                 
97                 public void CancelAllSubmissions ()
98                 {
99                         foreach (var sub in submissions) {
100                                 try {
101                                         if (!sub.IsCompleted)
102                                                 sub.Cancel ();
103                                 } catch (InvalidOperationException) {
104                                         // some submissions could be already done during this iteration. Ignore that.
105                                 }
106                         }
107                         submissions.Clear ();
108                 }
109
110                 public void EndBuild ()
111                 {
112                         if (ongoing_build_parameters == null)
113                                 throw new InvalidOperationException ("Build has not started");
114                         if (submissions.Count > 0)
115                                 WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
116                         ongoing_build_parameters = null;
117                 }
118                 
119                 Dictionary<Project,ProjectInstance> instances = new Dictionary<Project, ProjectInstance> ();
120
121                 public ProjectInstance GetProjectInstanceForBuild (Project project)
122                 {
123                         if (project == null)
124                                 throw new ArgumentNullException ("project");
125                         if (project.FullPath == null)
126                                 throw new ArgumentNullException ("project", "FullPath parameter in the project cannot be null.");
127                         if (project.FullPath == string.Empty)
128                                 throw new ArgumentException ("FullPath parameter in the project cannot be empty.", "project");
129                         // other than that, any invalid path character is accepted...
130                         
131                         return GetProjectInstanceForBuildInternal (project);
132                 }
133                         
134                 internal ProjectInstance GetProjectInstanceForBuildInternal (Project project)
135                 {
136                         if (!instances.ContainsKey (project))
137                                 instances [project] = project.CreateProjectInstance ();
138                         return instances [project];
139                 }
140
141                 public BuildSubmission PendBuildRequest (BuildRequestData requestData)
142                 {
143                         if (ongoing_build_parameters == null)
144                                 throw new InvalidOperationException ("This method cannot be called before calling BeginBuild method.");
145                         var sub = new BuildSubmission (this, requestData);
146                         submissions.Add (sub);
147                         return sub;
148                 }
149
150                 public void ResetCaches ()
151                 {
152                         if (OngoingBuildParameters != null)
153                                 throw new InvalidOperationException ("Cannot reset caches while builds are in progress.");
154                         
155                         BuildNodeManager.ResetCaches ();
156                 }
157                 
158                 BuildNodeManager build_node_manager;
159                 
160                 internal BuildNodeManager BuildNodeManager {
161                         get {
162                                 if (build_node_manager == null)
163                                                 build_node_manager = new BuildNodeManager (this);
164                                 return build_node_manager;
165                         }
166                 }
167         }
168 }