bovender framework
C# framework that implements MVVM and more
ReleaseInfo.cs
1 using Bovender.Text;
2 /* ReleaseInfo.cs
3  * part of Bovender framework
4  *
5  * Copyright 2014-2018 Daniel Kraus
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 using System;
20 using System.Collections.Generic;
21 using System.IO;
22 using System.Linq;
23 using System.Net;
24 using System.Text;
25 using System.Threading;
26 
27 namespace Bovender.Versioning
28 {
32  public class ReleaseInfo : Mvvm.Models.ProcessModel, IReleaseInfo
33  {
34  #region Public properties
35 
54  public Uri ReleaseInfoUri { get; protected set; }
55 
56  #endregion
57 
58  #region Implementation of IReleaseInfo
59 
60  public SemanticVersion ReleaseVersion { get; protected set; }
61 
62  public string Summary { get; protected set; }
63 
64  public Uri DownloadUri { get; protected set; }
65 
66  public string ExpectedHash { get; protected set; }
67 
68  public string RawReleaseInfo { get; protected set; }
69 
70  public ReleaseInfoStatus Status { get; protected set; }
71 
72  public Exception Exception { get; protected set; }
73 
74  public virtual bool Fetch()
75  {
76  bool result = false;
77  if (ReleaseInfoUri == null)
78  {
79  Status = ReleaseInfoStatus.FailureToFetch;
80  throw new InvalidOperationException("Cannot fetch release information, URI missing");
81  }
82  using (_webClient = new WebClient())
83  {
84  try
85  {
86  _webClient.DownloadStringCompleted += WebClient_DownloadStringCompleted;
87  var lockObject = new Object();
88  lock (lockObject)
89  {
90  _webClient.DownloadStringAsync(ReleaseInfoUri, lockObject);
91  Monitor.Wait(lockObject);
92  result = true;
93  }
94  }
95  catch (Exception e)
96  {
97  Exception = e;
98  SetDefaults();
99  Status = ReleaseInfoStatus.FailureToFetch;
100  }
101  }
102  return result;
103  }
104 
105  private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
106  {
107  lock (e.UserState)
108  {
109  Monitor.Pulse(e.UserState);
110  }
111  if (!e.Cancelled)
112  {
113  if (e.Error == null)
114  {
115  Logger.Info("WebClient_DownloadStringCompleted: Not cancelled and no error :-)");
116  RawReleaseInfo = e.Result;
117  Logger.Debug("WebClient_DownloadStringCompleted: \r\n{0}", RawReleaseInfo);
118  Status = Parse(RawReleaseInfo) ? ReleaseInfoStatus.InfoAvailable : ReleaseInfoStatus.FailureToParse;
119  }
120  else
121  {
122  Logger.Warn("WebClient_DownloadStringCompleted: Exception occurred while fetching release info");
123  Logger.Warn(e.Error);
124  Status = ReleaseInfoStatus.FailureToFetch;
125  Exception = e.Error;
126  }
127  }
128  else
129  {
130  Logger.Info("WebClient_DownloadStringCompleted: Fetching release info was cancelled");
131  Status = ReleaseInfoStatus.InfoUnavailable;
132  }
133  Logger.Info("WebClient_DownloadStringCompleted: Status: {0}", Status);
134  }
135 
136  #endregion
137 
138  #region Implementation of ProcessModel
139 
140  public override bool Execute()
141  {
142  return Fetch();
143  }
144 
145  #endregion
146 
147  #region Constructors
148 
153  public ReleaseInfo() : base() { }
154 
159  public ReleaseInfo(Uri releaseInfoUri)
160  : this()
161  {
162  ReleaseInfoUri = releaseInfoUri;
163  }
164 
165  #endregion
166 
167  #region Overrides
168 
169  protected override void OnCancelling()
170  {
171  base.OnCancelling();
172  if (_webClient != null && _webClient.IsBusy)
173  {
174  _webClient.CancelAsync();
175  }
176  }
177 
178  #endregion
179 
180  #region Protected methods
181 
182  protected virtual bool Parse(string rawInfo)
183  {
184  bool result = false;
185  using (StringReader r = new StringReader(rawInfo))
186  {
187  try
188  {
189  ReleaseVersion = new SemanticVersion(r.ReadLine());
190  string rawUri = r.ReadLine();
191  // If the raw URI contains the placeholder $VERSION, replace
192  // it with the new version.
193  DownloadUri = new Uri(rawUri.Replace("$VERSION", ReleaseVersion.ToString()));
194  // Use only the first word of the line as Sha1 sum
195  // to make it compatible with the output of `sha1sum`
196  ExpectedHash = r.ReadLine().Trim().Split(' ')[0];
197  Multiline multi = new Multiline(r.ReadToEnd(), true);
198  Summary = multi.Text;
199  Status = ReleaseInfoStatus.InfoAvailable;
200  result = true;
201  }
202  catch (Exception e)
203  {
204  SetDefaults();
205  Status = ReleaseInfoStatus.FailureToParse;
206  Exception = e;
207  }
208  }
209  return result;
210  }
211 
212  protected virtual void SetDefaults()
213  {
214  ReleaseVersion = null;
215  DownloadUri = null;
216  Summary = String.Empty;
217  ExpectedHash = String.Empty;
218  }
219 
220  #endregion
221 
222  #region Private fields
223 
224  private WebClient _webClient;
225 
226  #endregion
227 
228  #region Class logger
229 
230  private static NLog.Logger Logger { get { return _logger.Value; } }
231 
232  private static readonly Lazy<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
233 
234  #endregion
235  }
236 }
Represents a text with multiple lines.
Definition: Multiline.cs:31
override bool Execute()
This method may be called by a ProcessViewModelBase-derived class in a worker task that wraps this me...
Definition: ReleaseInfo.cs:140
Interface for classes that fetch current release information.
Definition: IReleaseInfo.cs:30
virtual bool Fetch()
Updates the release information.
Definition: ReleaseInfo.cs:74
ReleaseInfo()
Creates a new ReleaseInfo object that can fetch release information from the internet.
Definition: ReleaseInfo.cs:153
string Text
Gets the multiline text as a single string.
Definition: Multiline.cs:39
ReleaseInfo(Uri releaseInfoUri)
Creates a new ReleaseInfo object that can fetch release information from the internet using the URI g...
Definition: ReleaseInfo.cs:159
Class that handles semantic versioning.
Fetches and digests release information.
Definition: ReleaseInfo.cs:32