Merge pull request #924 from marcusva/master
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Execution / BuildSubmission.cs
1 // BuildSubmission.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 System;
30 using System.Threading;
31 using System.Threading.Tasks;
32 using System.Linq;
33 using Microsoft.Build.Framework;
34 using Microsoft.Build.Internal;
35 using System.Collections.Generic;
36
37 namespace Microsoft.Build.Execution
38 {
39         public class BuildSubmission
40         {
41                 static Random rnd = new Random ();
42
43                 internal BuildSubmission (BuildManager build, BuildRequestData requestData)
44                 {
45                         BuildManager = build;
46                         this.request = requestData;
47                         SubmissionId = rnd.Next ();
48                 }
49
50                 BuildRequestData request;
51                 BuildSubmissionCompleteCallback callback;
52                 bool is_started, is_completed, is_canceled;
53                 ManualResetEvent wait_handle = new ManualResetEvent (true);
54
55                 public object AsyncContext { get; private set; }
56                 public BuildManager BuildManager { get; private set; }
57                 public BuildResult BuildResult { get; set; }
58                 public bool IsCompleted {
59                         get { return is_completed; }
60                 }
61                 public int SubmissionId { get; private set; }
62                 public WaitHandle WaitHandle {
63                         get { return wait_handle; }
64                 }
65                 
66                 internal BuildRequestData BuildRequest {
67                         get { return this.request; }
68                 }
69
70                 internal void Cancel ()
71                 {
72                         if (is_canceled)
73                                 throw new InvalidOperationException ("Build has already canceled");
74                         is_canceled = true;
75                 }
76
77                 public BuildResult Execute ()
78                 {
79                         ExecuteAsync (null, null);
80                         WaitHandle.WaitOne ();
81                         return BuildResult;
82                 }
83                 
84                 internal BuildResult InternalExecute ()
85                 {
86                         BuildResult = new BuildResult () { SubmissionId = SubmissionId };
87                         try {
88                                 var engine = new BuildEngine4 (this);
89                                 string toolsVersion = request.ExplicitlySpecifiedToolsVersion ?? request.ProjectInstance.ToolsVersion ?? BuildManager.OngoingBuildParameters.DefaultToolsVersion;
90                                 var outputs = new Dictionary<string,string> ();
91                                 engine.BuildProject (() => is_canceled, BuildResult, request.ProjectInstance, request.TargetNames, BuildManager.OngoingBuildParameters.GlobalProperties, outputs, toolsVersion);
92                         } catch (Exception ex) {
93                                 BuildResult.Exception = ex;
94                                 BuildResult.OverallResult = BuildResultCode.Failure;
95                         }
96                         is_completed = true;
97                         if (callback != null)
98                                 callback (this);
99                         wait_handle.Set ();
100                         return BuildResult;
101                 }
102
103                 public void ExecuteAsync (BuildSubmissionCompleteCallback callback, object context)
104                 {
105                         if (is_completed)
106                                 throw new InvalidOperationException ("Build has already completed");
107                         if (is_canceled)
108                                 throw new InvalidOperationException ("Build has already canceled");
109                         if (is_started)
110                                 throw new InvalidOperationException ("Build has already started");
111                         is_started = true;
112                         this.AsyncContext = context;
113                         this.callback = callback;
114                         wait_handle.Reset ();
115                         
116                         BuildManager.BuildNodeManager.Enqueue (this);
117                 }
118         }
119 }
120