private static void UploadTaskCallback(UploadTask task) {

            try {

                if (task.Stream != null) {
                    task.Stream.Close();
                }

                OnUploadTaskDone(task);

                // Invoke 'OnUploadedVersion' on the viewmodel
                // This should maybe be done nicer, interface?
                Session.ScheduleTask(task.SessionId, (Session session, String sessionId) => {
                    if (sessionId == task.SessionId) {
                        if (session.Data is WarehouseMainPage) {
                            if (((WarehouseMainPage)session.Data).Partial is ApplicationPage) {
                                ApplicationPage page = ((WarehouseMainPage)session.Data).Partial as ApplicationPage;
                                page.OnUploadedVersion(task.UploadFileName, task.Version);
                                session.CalculatePatchAndPushOnWebSocket();
                            }
                            else if (((WarehouseMainPage)session.Data).Partial is UploadVersionsPage) {
                                UploadVersionsPage page = ((WarehouseMainPage)session.Data).Partial as UploadVersionsPage;
                                page.OnUploadedVersion(task.UploadFileName, task.Version);
                                session.CalculatePatchAndPushOnWebSocket();
                            }
                        }
                    }
                });
            }
            catch (Exception e) {

                string message = e.Message;

                try {
                    if (File.Exists(task.TempFilename)) {
                        File.Delete(task.TempFilename);
                    }
                }
                catch (Exception) {
                    message += ". Failed to cleanup temp file";
                }


                // Invoke 'OnInvalidUploadVersion' on the viewmodel
                // This should maybe be done nicer, interface?
                Session.ScheduleTask(task.SessionId, (Session session, String sessionId) => {
                    if (sessionId == task.SessionId) {
                        if (session.Data is WarehouseMainPage) {
                            if (((WarehouseMainPage)session.Data).Partial is ApplicationPage) {
                                ApplicationPage page = ((WarehouseMainPage)session.Data).Partial as ApplicationPage;
                                page.OnInvalidUploadVersion(task.UploadFileName, message);
                                session.CalculatePatchAndPushOnWebSocket();
                            }
                            else if (((WarehouseMainPage)session.Data).Partial is UploadVersionsPage) {
                                UploadVersionsPage page = ((WarehouseMainPage)session.Data).Partial as UploadVersionsPage;
                                page.OnInvalidUploadVersion(task.UploadFileName, message);
                                session.CalculatePatchAndPushOnWebSocket();
                            }
                        }
                    }
                });
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="task"></param>
        private static void OnUploadTaskDone(UploadTask task) {

            string file = null;

            PackageManager.VerifyPacket(task.TempFilename);

            PackageConfigFile config;
            PackageManager.ReadConfiguration(task.TempFilename, out config);

            // Get Resource object
            IObjectView obj = DbHelper.FromID(DbHelper.Base64DecodeObjectID(task.ResourceId));

            Organization organization = null;
            Software software = null;

            if (obj is App) {
                software = (Software)obj;
                organization = software.Organization;

                if (!string.Equals(config.Namespace, software.Namespace, StringComparison.InvariantCultureIgnoreCase)) {
                    throw new InvalidOperationException(string.Format("Uploaded version namespace ({0}) does not match application namespace ({1}).", config.Namespace, software.Namespace));
                }
            }
            else if (obj is Organization) {
                organization = obj as Organization;
            }

            if (organization == null) {
                throw new InvalidOperationException("Upload on a non organization resource");
            }

            try {

                // Move and name the temp file to it's correct place
                file = MoveUploadedFile(task.TempFilename, organization, config.Namespace, config.Channel, config.Version);

                Db.Transact(() => {

                    // Find software
                    software = Db.SQL<Software>("SELECT o FROM Warehouse.Software o WHERE o.Organization=? AND o.Namespace=?", organization, config.Namespace).First;
                    if (software == null) {
                        // Auto-create application
                        software = CreateApplication(config, organization, task.SessionId);
                    }
                    else {

                        // Check if Version already exists.
                        Version duplicatedVersion = Db.SQL<Version>("SELECT o FROM Warehouse.Version o WHERE o.Software=? AND o.Name=? AND o.Channel=?", software, config.Version, config.Channel).First;
                        if (duplicatedVersion != null) {
                            throw new InvalidOperationException("Version already exist");
                        }
                    }

                    Settings settings = Settings.GetSettings();
                    if (settings == null) {
                        throw new InvalidOperationException("Warehouse has not be configured, Visit the settings page.");
                    }
                    string folder = Path.Combine(settings.PublicFolder, "warehouse");
                    folder = Path.Combine(folder, "images");
                    UnpackAppStoreMetadata(software, file, config, folder);

                    // Create version database instance
                    Version version = new Version();

                    version.ID = string.Format("{0:X8}", (software.ID + config.Channel + config.VersionDate).GetHashCode());
                    version.Name = config.Version;
                    version.Software = software;
                    version.BinaryFile = file;
                    version.VersionDate = config.VersionDate;
                    version.Channel = config.Channel;


                    // Add AppVersion Dependencies
                    if (config.Dependencies != null) {
                        foreach (Dependency dependency in config.Dependencies) {
                            if (String.Equals("Starcounter", dependency.Name, StringComparison.InvariantCultureIgnoreCase)) {
                                version.Compatiblility = dependency.Value;
                                break;
                            }
                            // dependency.Name;    // "Starcounter"
                            // dependency.Value;  // "~2.1.284"
                        }
                    }

                    task.Version = version; // Update task
                });

                // Push changed to viewmodel
                Session.ScheduleTask(task.SessionId, (Session session, String sessionId) => {
                    if (session != null && session.IsAlive()) {
                        session.CalculatePatchAndPushOnWebSocket();
                    }
                });

            }
            catch (Exception) {

                if (file != null) {

                    if (File.Exists(file)) {
                        File.Delete(file);
                    }

                    DirectoryInfo di = Directory.GetParent(file);
                    if (Utils.IsDirectoryEmpty(di.FullName)) {
                        Directory.Delete(di.FullName);
                    }
                }

                throw;
            }
        }
        /// <summary>
        /// Create upload task
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="fileName"></param>
        /// <param name="fileSize"></param>
        /// <param name="resourceId">Object id where the upload should be related to</param>
        /// <returns></returns>
        private static UploadTask CreateUploadTask(string sessionId, string fileName, int fileSize, string resourceId) {

            string tempFileName = GenerateUploadTempFileName();
            var fs = new FileStream(tempFileName, FileMode.Append);
            UploadTask ut = new UploadTask() { SessionId = sessionId, Stream = fs, FileSize = fileSize, UploadFileName = fileName, ResourceId = resourceId };

            ut.DoneCallback = UploadTaskCallback;
            return ut;
        }