aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs
blob: 52eb2bbb5e77e542f4343d46efcb527f07b664fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tango.BL;
using Tango.MachineService.Filters;
using Tango.MachineService.Models;
using Tango.Web.Helpers;
using System.Data.Entity;
using Tango.Web.Storage;
using System.IO;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
using System.Net.Mime;
using Tango.MachineService.Views.FSEDownloads;

namespace Tango.MachineService.Controllers
{
    public class FSEDownloadsController : Controller
    {
        public ActionResult Index()
        {
            IndexViewModel model = new IndexViewModel();

            using (var db = ObservablesContextHelper.CreateContext())
            {
                var versions = db.FseVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).Take(6).ToList();

                var manager = new BlobStorageManager();
                var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER);

                foreach (var item in versions)
                {
                    var installerBlob = container.GetBlockBlobReference(item.InstallerBlobName);

                    model.Downloads.Add(new FSEDownload()
                    {
                        Name = $"Tango FSE v{Version.Parse(item.Version).ToString(3)}",
                        Version = Version.Parse(item.Version).ToString(3),
                        Comments = item.Comments,
                        Date = item.LastUpdated.ToString("dddd, dd MMMM yyyy"),
                        Address = MachineServiceConfig.CDN_ENDPOINT + installerBlob.Uri.AbsolutePath
                    });
                }

                if (model.Downloads.Count > 0)
                {
                    var latest = model.Downloads.First();
                    model.Downloads.Remove(latest);
                    model.LatestDownload = latest;
                }
            }

            return View(model);
        }
    }
}
/span>/// DTD: "<!DOCTYPE" (RawText+ RawTag)* RawText* ">" (DOCTYPE or other DTD names) /// UknownBang: "<!" (RawText)* ">" /// ]]> /// /// The type of tag can be identified by the opening backet. /// There are helpper properties in the RawTag class to identify the type, exactly /// one of the properties will be true. /// /// The closing bracket may be missing or may be different for mallformed XML. /// /// Note that there can always be multiple consequtive RawText nodes. /// This is to ensure that idividual texts are not too long. /// /// XML Spec: http://www.w3.org/TR/xml/ /// XML EBNF: http://www.jelks.nu/XML/xmlebnf.html /// /// Internals: /// /// "Try" methods can silently fail by returning false. /// MoveTo methods do not move if they are already at the given target /// If methods return some object, it must be no-empty. It is up to the caller to ensure /// the context is appropriate for reading. /// /// </remarks> public class AXmlParser { AXmlDocument userDocument; internal TrackedSegmentCollection TrackedSegments { get; private set; } /// <summary> /// Generate syntax error when seeing enity reference other then the build-in ones /// </summary> public bool UnknownEntityReferenceIsError { get; set; } /// <summary> Create new parser </summary> public AXmlParser() { this.Lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); ClearInternal(); } /// <summary> Throws exception if condition is false </summary> internal static void Assert(bool condition, string message) { if (!condition) { throw new InternalException("Assertion failed: " + message); } } /// <summary> Throws exception if condition is false </summary> [Conditional("DEBUG")] internal static void DebugAssert(bool condition, string message) { if (!condition) { throw new InternalException("Assertion failed: " + message); } } [Conditional("DEBUG")] internal static void Log(string text, params object[] pars) { //System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "XML: " + text, pars)); } /// <summary> /// Incrementaly parse the given text. /// You have to hold the write lock. /// </summary> /// <param name="input"> /// The full XML text of the new document. /// </param> /// <param name="changesSinceLastParse"> /// Changes since last parse. Null will cause full reparse. /// </param> public AXmlDocument Parse(string input, IEnumerable<DocumentChangeEventArgs> changesSinceLastParse) { if (!Lock.IsWriteLockHeld) throw new InvalidOperationException("Lock needed!"); // Use changes to invalidate cache if (changesSinceLastParse != null) { this.TrackedSegments.UpdateOffsetsAndInvalidate(changesSinceLastParse); } else { this.TrackedSegments.InvalidateAll(); } TagReader tagReader = new TagReader(this, input); List<AXmlObject> tags = tagReader.ReadAllTags(); AXmlDocument parsedDocument = new TagMatchingHeuristics(this, input, tags).ReadDocument(); tagReader.PrintStringCacheStats(); AXmlParser.Log("Updating main DOM tree..."); userDocument.UpdateTreeFrom(parsedDocument); userDocument.DebugCheckConsistency(true); Assert(userDocument.GetSelfAndAllChildren().Count() == parsedDocument.GetSelfAndAllChildren().Count(), "Parsed document and updated document have different number of children"); return userDocument; } /// <summary> /// Makes calls to Parse() thread-safe. Use Lock everywhere Parse() is called. /// </summary> public ReaderWriterLockSlim Lock { get; private set; } /// <summary> /// Returns the last cached version of the document. /// </summary> /// <exception cref="InvalidOperationException">No read lock is held by the current thread.</exception> public AXmlDocument LastDocument { get { if (!Lock.IsReadLockHeld) throw new InvalidOperationException("Read lock needed!"); return userDocument; } } /// <summary> /// Clears the parser data. /// </summary> /// <exception cref="InvalidOperationException">No write lock is held by the current thread.</exception> public void Clear() { if (!Lock.IsWriteLockHeld) throw new InvalidOperationException("Write lock needed!"); ClearInternal(); } void ClearInternal() { this.UnknownEntityReferenceIsError = true; this.TrackedSegments = new TrackedSegmentCollection(); this.userDocument = new AXmlDocument() { Parser = this }; this.userDocument.Document = this.userDocument; // Track the document this.TrackedSegments.AddParsedObject(this.userDocument, null); this.userDocument.IsCached = false; } } }