Esempio n. 1
0
        /// <summary>
        /// Gets a collection from the cache
        /// </summary>
        /// <param name="collectionIdentifier"></param>
        /// <returns></returns>
        private async Task <IonCollection> getCollectionFromCacheAsync(CollectionCacheIndex cacheIndex, bool serverCallAsBackup)
        {
            string collectionURL = PagesURLs.getCollectionURL(_config);

            // retrieve from memory cache
            IonCollection collection = _memoryCache.collection;

            if (collection != null)
            {
                return(collection);
            }

            // try to load collection from isolated storage
            try
            {
                collection = await StorageUtils.loadCollectionFromIsolatedStorageAsync(_config).ConfigureAwait(false);

                // Add collection to memory cache
                if (collection != null)
                {
                    _memoryCache.collection = collection;
                }
            }
            catch (Exception e)
            {
                IonLogging.log("Error getting collection from isolated storage. Message: " + e.Message, IonLogMessageTypes.ERROR);
            }

            return(collection);
        }
Esempio n. 2
0
        /// <summary>
        /// Used to retrieve a class that inherits from CacheIndex
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="collectionIdentifier"></param>
        /// <returns>First it tries to get a index from memoryCache, then from fileCache and after that returns null, if no index is found</returns>
        public static async Task <T> retrieve <T>(string requestUrl, IonConfig config) where T : CacheIndex
        {
            T index = MemoryCacheIndex.get <T>(requestUrl, config.collectionIdentifier);

            if (index != null)
            {
                IonLogging.log("Index lookup " + requestUrl + " from memory", IonLogMessageTypes.SUCCESS);
                return(index);
            }

            // check isolated storage
            try
            {
                index = await StorageUtils.getIndexAsync <T>(requestUrl, config).ConfigureAwait(false);

                if (index != null)
                {
                    IonLogging.log("Index lookup " + requestUrl + " from isolated storage", IonLogMessageTypes.SUCCESS);
                }
            }
            catch (Exception e)
            {
                IonLogging.log("Index lookup " + requestUrl + " is not in isolated storage. Message: " + e.Message, IonLogMessageTypes.INFORMATION);
            }

            // Save to memory cache, if index is not null
            if (index != null)
            {
                MemoryCacheIndex.put(requestUrl, config.collectionIdentifier, index);
            }

            return(index);
        }
Esempio n. 3
0
        /// <summary>
        /// Used to get a page with a desired identifier
        /// </summary>
        /// <param name="pageIdentifier"></param>
        /// <returns>Already parsed IonPage</returns>
        public async Task <IonPage> getPageAsync(string pageIdentifier)
        {
            string         pageURL        = PagesURLs.getPageURL(_config, pageIdentifier);
            PageCacheIndex pageCacheIndex = await PageCacheIndex.retrieve(pageURL, _config).ConfigureAwait(false);

            bool isNetworkConnected = NetworkUtils.isOnline();

            if (pageCacheIndex == null)
            {
                if (isNetworkConnected)
                {
                    IonLogging.log("Loading page \"" + pageIdentifier + "\" from server.", IonLogMessageTypes.SUCCESS);
                    return(await getPageFromServerAsync(pageIdentifier).ConfigureAwait(false));
                }
                else
                {
                    IonLogging.log("Error getting page \"" + pageIdentifier + "\" from server or cache.", IonLogMessageTypes.ERROR);
                    throw new PageNotAvailableException();
                }
            }

            // Get collection
            IonCollection collection = await getCollectionAsync().ConfigureAwait(false);

            // Get last changed of the page from collection
            DateTime pageLastChanged = collection.getPageLastChanged(pageIdentifier);

            // Estimate, if the page is outdated or not
            bool isOutdated = pageCacheIndex.isOutdated(pageLastChanged);

            if (!isOutdated)
            {
                IonLogging.log("Loading page \"" + pageIdentifier + "\" from cache.", IonLogMessageTypes.SUCCESS);
                return(await getPageFromCacheAsync(pageIdentifier).ConfigureAwait(false));
            }
            else
            {
                if (isNetworkConnected)
                {
                    // Download page from server
                    IonLogging.log("Loading newer version of page \"" + pageIdentifier + "\" from server.", IonLogMessageTypes.SUCCESS);
                    return(await getPageFromServerAsync(pageIdentifier).ConfigureAwait(false));
                }
                else
                {
                    // get old version from cache
                    IonLogging.log("Loading potentially old version of page \"" + pageIdentifier + "\" from cache.", IonLogMessageTypes.WARNING);
                    return(await getPageFromCacheAsync(pageIdentifier).ConfigureAwait(false));
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Saves a index to memory and isolated storage cache
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="requestURL"></param>
        /// <param name="cacheIndex"></param>
        /// <param name="config"></param>
        public static async Task save <T>(string requestURL, T cacheIndex, IonConfig config) where T : CacheIndex
        {
            try
            {
                // save to memory cache
                MemoryCacheIndex.put <T>(requestURL, config.collectionIdentifier, cacheIndex);

                // save to isolated storage
                await StorageUtils.saveIndexAsync(requestURL, cacheIndex, config).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                IonLogging.log("Cache Index " + requestURL + " could not be saved. Message: " + e.Message, IonLogMessageTypes.ERROR);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Clears the memory and file caches
        /// </summary>
        /// <param name="collectionIdentifier"></param>
        /// <param name="locale"></param>
        public static async Task clear(string collectionIdentifier)
        {
            try
            {
                // Clear memory cache
                MemoryCacheIndex.clear(collectionIdentifier);

                // Clear isolated storage cache
                await StorageUtils.deleteFolderInIsolatedStorageAsync(collectionIdentifier).ConfigureAwait(false);
            }

            catch (Exception e)
            {
                IonLogging.log("Error cleaning caches: " + e.Message, IonLogMessageTypes.ERROR);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Checks the cache for a possible duplicate and removes it
        /// </summary>
        /// <param name="key"></param>
        private void removePossibleDouplicate(K key)
        {
            // Check if there is a existing node with the specified key
            LinkedListNode <LRUCacheItem <K, V> > node;

            if (cacheMap.TryGetValue(key, out node))
            {
                // Decrease capacity
                _capacity -= node.Value.sizeInByte;

                // Remove node from the lruList
                lruList.Remove(node);

                // Remove key from the cacheMap
                cacheMap.Remove(key);

                IonLogging.log("Removed duplicate node from LRU-Cache with the key: " + key.ToString(), IonLogMessageTypes.INFORMATION);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Used to get the collection of the class
        /// </summary>
        /// <returns>The collection of this pages</returns>
        public async Task <IonCollection> getCollectionAsync()
        {
            string collectionURL            = PagesURLs.getCollectionURL(_config);
            CollectionCacheIndex cacheIndex = await CollectionCacheIndex.retrieve(collectionURL, _config).ConfigureAwait(false);

            // Check if there is a not outdated cacheIndex avialible
            bool currentCacheEntry = cacheIndex != null && !cacheIndex.isOutdated(_config);
            bool networkConnected  = NetworkUtils.isOnline();


            if (currentCacheEntry)
            {
                // retrieve current version from cache
                IonLogging.log("Loading collection \"" + _config.collectionIdentifier + "\" from cache.", IonLogMessageTypes.SUCCESS);
                return(await getCollectionFromCacheAsync(cacheIndex, false).ConfigureAwait(false));
            }
            else
            {
                if (networkConnected)
                {
                    // download collection or check for modifications
                    IonLogging.log("Loading collection \"" + _config.collectionIdentifier + "\" from server.", IonLogMessageTypes.SUCCESS);
                    return(await getCollectionFromServerAsync(cacheIndex, false).ConfigureAwait(false));
                }
                else
                {
                    if (cacheIndex != null)
                    {
                        // no network: use potential old version from cache
                        IonLogging.log("Using potentially old version of collection \"" + _config.collectionIdentifier + "\" from cache, because there is no internet connection.", IonLogMessageTypes.WARNING);
                        return(await getCollectionFromCacheAsync(cacheIndex, false).ConfigureAwait(false));
                    }
                    else
                    {
                        // Collection can neither be downloaded nor be found in cache
                        IonLogging.log("Couldn't get collection \"" + _config.collectionIdentifier + "\" either from server or cache.", IonLogMessageTypes.ERROR);
                        throw new CollectionNotAvailableException();
                    }
                }
            }
        }
        // login to get access token
        public static async Task <AuthenticationHeaderValue> GetAuthHeaderValue(string username, string password, string loginAdress)
        {
            // Temporary httpClient for the login process
            HttpClient loginClient = new HttpClient();

            // Login data object
            Login loginData;

            // Generate POST request
            Dictionary <string, string> request = new Dictionary <string, string>();

            request.Add("username", username);
            request.Add("password", password);

            FormUrlEncodedContent requestContent = new FormUrlEncodedContent(request);


            try
            {
                // Post request to server
                HttpResponseMessage response = await loginClient.PostAsync(new Uri( loginAdress ), requestContent).ConfigureAwait(false);

                // Process and return the acces token
                string jsonResult = response.Content.ReadAsStringAsync().Result;

                // Generate the model and try to parse the answer from the server
                LoginRootObject lro = new LoginRootObject();

                loginData = JsonConvert.DeserializeObject <LoginRootObject>(jsonResult).login;

                // Create the http authentication header
                return(new AuthenticationHeaderValue("Token", loginData.token));
            }

            catch (Exception e)
            {
                IonLogging.log("Error logging in: " + e.Message, IonLogMessageTypes.ERROR);
                return(null);
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Gets a page directly from the server
        /// </summary>
        /// <param name="pageIdentifier"></param>
        /// <returns></returns>
        private async Task <IonPage> getPageFromServerAsync(string pageIdentifier)
        {
            try
            {
                // Retrieve the page from the server
                HttpResponseMessage response = await _dataClient.getPageAsync(pageIdentifier).ConfigureAwait(false);

                IonPage page = await DataParser.parsePageAsync(response).ConfigureAwait(false);

                // Add page to cache, if it is not null
                if (page != null)
                {
                    await savePageToCachesAsync(page, _config);
                }

                return(page);
            }
            catch (Exception e)
            {
                IonLogging.log("Error getting page " + pageIdentifier + " from server! " + e.Message, IonLogMessageTypes.ERROR);
                return(null);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Parses a given pageString to a IonPage
        /// </summary>
        /// <param name="pageString"></param>
        /// <returns>Parsed IonPage</returns>
        public static IonPage parsePage(string pageString)
        {
            // Parse the page to a raw page container
            IonPage pageParsed = new IonPage();

            try
            {
                // Deserialize page
                IonPageRoot pageParsedNew = JsonConvert.DeserializeObject <IonPageRoot>(pageString);

                // Set the first element of the root to be the page
                pageParsed = pageParsedNew.page[0];

                // Sort out empty content
                pageParsed.sortOutEmptyContent();
            }
            catch (Exception e)
            {
                IonLogging.log("Error deserializing page json: " + e.Message, IonLogMessageTypes.ERROR);
            }

            return(pageParsed);
        }
Esempio n. 11
0
        /// <summary>
        /// Gets a collection from the server
        /// </summary>
        /// <param name="collectionIdentifier"></param>
        /// <returns></returns>
        private async Task <IonCollection> getCollectionFromServerAsync(CollectionCacheIndex cacheIndex, bool cacheAsBackup)
        {
            //DateTime lastModified = cacheIndex != null ? cacheIndex.lastModified : DateTime.MinValue;

            try
            {
                // Retrive collecion from server and parse it
                HttpResponseMessage response = await _dataClient.getCollectionAsync(_config.collectionIdentifier, cacheIndex != null?cacheIndex.lastModified : DateTime.MinValue).ConfigureAwait(false);

                // Only parse the answer if it is not newer than the cached version
                if (!(response.StatusCode == System.Net.HttpStatusCode.NotModified))
                {
                    // Parse collection
                    IonCollection collection = await DataParser.parseCollectionAsync(response).ConfigureAwait(false);

                    // Add collection to memory cache
                    _memoryCache.collection = collection;

                    // Save collection to isolated storage
                    await StorageUtils.saveCollectionToIsolatedStorageAsync(collection, _config).ConfigureAwait(false);

                    // save cacheIndex
                    await saveCollectionCacheIndexAsync(collection.last_changed).ConfigureAwait(false);

                    return(collection);
                }
                else
                {
                    // Collection in the server is the same as stored already in isolated storage cache
                    if (_memoryCache.collection == null)
                    {
                        // Only load collection from isolated storage cache, if the memory cache has no collection cached
                        try
                        {
                            // Get collection from isolated storage
                            IonCollection collection = await StorageUtils.loadCollectionFromIsolatedStorageAsync(_config).ConfigureAwait(false);

                            // Add collection to memory cache
                            if (collection != null)
                            {
                                _memoryCache.collection = collection;
                            }

                            // change the last-mofied date in the cacheIndex to now
                            await saveCollectionCacheIndexAsync(collection.last_changed).ConfigureAwait(false);

                            return(collection);
                        }
                        catch (Exception e)
                        {
                            IonLogging.log("Error getting collection from isolated storage. Message: " + e.Message, IonLogMessageTypes.ERROR);
                            return(null);
                        }
                    }
                    else
                    {
                        // change the last-mofied date in the cacheIndex to now
                        await saveCollectionCacheIndexAsync(_memoryCache.collection.last_changed).ConfigureAwait(false);

                        return(_memoryCache.collection);
                    }
                }
            }
            catch (Exception e)
            {
                IonLogging.log("Error retreiving collection data: " + e.Message, IonLogMessageTypes.ERROR);
                return(null);
            }
        }
        /// <summary>
        /// Used to load and extract an archive to the caches
        /// </summary>
        /// <param name="ionFiles"></param>
        /// <param name="ionPages"></param>
        /// <param name="url"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public async Task loadArchiveAsync(IIonFiles ionFiles, IIonPages ionPages, string url, Action callback = null)
        {
            // Temporary used elements in the isolated storage
            StorageFile   archiveFile = null;
            StorageFolder tempFolder  = null;

            // Get temp-folder path
            string tempFolderPath = FilePaths.getTempFolderPath(_config);

            // Lock all used elements
            using (await _fileLocks.ObtainLock(url).LockAsync().ConfigureAwait(false))
                using (await _fileLocks.ObtainLock(tempFolderPath).LockAsync().ConfigureAwait(false))
                {
                    try
                    {
                        // Request archive file
                        archiveFile = await ionFiles.requestArchiveFileAsync(url);

                        // Get tempFolder for extraction
                        tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(tempFolderPath, CreationCollisionOption.ReplaceExisting);

                        // Generate fileStream from archiveFile
                        using (Stream stream = (Stream)await archiveFile.OpenStreamForReadAsync())
                        {
                            // Extract file to tempFolder
                            await TarUtils.ExtractTarArchiveAsync(stream, tempFolder).ConfigureAwait(false);
                        }

                        // Get all elements listed in the index file
                        string indexFileString = await FileIO.ReadTextAsync(await tempFolder.GetFileAsync("index.json"));

                        List <ArchiveElement> elementsList = JsonConvert.DeserializeObject <List <ArchiveElement> >(indexFileString);

                        // Handle each element of the index.json
                        for (int i = 0; i < elementsList.Count; i++)
                        {
                            IonRequestInfo requestInfo = PagesURLs.analyze(elementsList[i].url, _config);

                            // Treat every element regarding its type
                            switch (requestInfo.requestType)
                            {
                            case IonRequestType.MEDIA:
                            {
                                // Get all the needed folder- and file names
                                StorageFolder mediaFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(FilePaths.getMediaFolderPath(_config, false), CreationCollisionOption.OpenIfExists);

                                string sourcePath      = tempFolder.Path + IonConstants.BackSlash + elementsList[i].name.Replace('/', (char)IonConstants.BackSlash[0]);
                                string destinationPath = mediaFolder.Path + IonConstants.BackSlash + FilePaths.getFileName(elementsList[i].url);

                                // Delete a possible existing file
                                if (File.Exists(destinationPath))
                                {
                                    File.Delete(destinationPath);
                                }

                                // Move the file from the temp to the media folder
                                File.Move(sourcePath, destinationPath);

                                // Create index for file
                                FileCacheIndex index = new FileCacheIndex(elementsList[i].url, elementsList[i].checksum, DateTimeUtils.now());

                                // Save file index
                                await CacheIndexStore.save(elementsList[i].url, index, _config).ConfigureAwait(false);

                                break;
                            }

                            case IonRequestType.PAGE:
                            {
                                // Extract the page json from the file
                                string pageString = await FileIO.ReadTextAsync(await tempFolder.GetFileAsync(elementsList[i].name.Replace('/', (char)IonConstants.BackSlash[0])));

                                // Parse the new page
                                IonPage page = DataParser.parsePage(pageString);

                                // Save the page to the caches
                                await ionPages.savePageToCachesAsync(page, _config).ConfigureAwait(false);

                                break;
                            }

                            default:
                            {
                                IonLogging.log("Object " + elementsList[i].url + " could not be parsed from archive.", IonLogMessageTypes.ERROR);
                                break;
                            }
                            }
                        }
                    }

                    catch (Exception e)
                    {
                        IonLogging.log("Error at the archive download: " + e.Message, IonLogMessageTypes.ERROR);
                    }

                    finally
                    {
                        // Clean up all temperary used elements
                        if (archiveFile != null)
                        {
                            // Delete index file
                            string indexFilePath = FilePaths.getCacheIndicesFolderPath(_config) + IonConstants.BackSlash + archiveFile.Name + IonConstants.JsonFileExtension;

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

                            // Delete archive file
                            await archiveFile.DeleteAsync();
                        }

                        if (tempFolder != null)
                        {
                            await tempFolder.DeleteAsync();
                        }

                        // Call the callback action if set before
                        if (callback != null)
                        {
                            callback();
                        }
                    }
                }

            // Release the file locks
            _fileLocks.ReleaseLock(url);
            _fileLocks.ReleaseLock(tempFolderPath);
        }