2018-01-17 21:47:05 -08:00
/ *
Copyright ( c ) 2014 , Lars Brubaker
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
using System ;
2019-05-23 08:28:50 -07:00
using System.Diagnostics.CodeAnalysis ;
2018-01-17 21:47:05 -08:00
using System.IO ;
namespace MatterHackers.MatterControl.DataStorage
{
2019-05-23 08:28:50 -07:00
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "Private getters used to enforce presence of directories")]
2018-01-17 21:47:05 -08:00
public class ApplicationDataStorage
{
2019-05-23 08:28:50 -07:00
// Required by Android
public bool FirstRun { get ; set ; } = false ;
2018-01-17 21:47:05 -08:00
2019-05-23 08:28:50 -07:00
// Describes the location for storing all local application data
2018-01-17 21:47:05 -08:00
private static ApplicationDataStorage globalInstance ;
2018-01-17 22:12:01 -08:00
2019-05-23 08:28:50 -07:00
private const string ApplicationDataFolderName = "MatterControl" ;
private const string DatastoreName = "MatterControl.db" ;
private string _applicationPath ;
2018-01-17 21:47:05 -08:00
public static ApplicationDataStorage Instance
{
get
{
if ( globalInstance = = null )
{
globalInstance = new ApplicationDataStorage ( ) ;
}
2019-05-23 08:28:50 -07:00
2018-01-17 21:47:05 -08:00
return globalInstance ;
}
}
2018-01-17 22:07:53 -08:00
public string ApplicationPath
2018-01-17 21:47:05 -08:00
{
2018-01-17 22:07:53 -08:00
get
{
if ( _applicationPath = = null )
{
_applicationPath = Path . GetDirectoryName ( System . Reflection . Assembly . GetExecutingAssembly ( ) . Location ) ;
}
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
return _applicationPath ;
}
2018-01-17 21:47:05 -08:00
}
2019-05-23 08:28:50 -07:00
private static string _applicationUserDataPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , ApplicationDataFolderName ) ;
2018-01-18 11:33:08 -08:00
private static string _applicationLibraryDataPath = > Path . Combine ( _applicationUserDataPath , "Library" ) ;
2019-05-23 08:28:50 -07:00
2018-01-18 11:33:08 -08:00
private static string _libraryAssetPath = > Path . Combine ( _applicationLibraryDataPath , "Assets" ) ;
2019-05-23 08:28:50 -07:00
2018-01-18 11:33:08 -08:00
private static string _platingDirectory = > Path . Combine ( _applicationLibraryDataPath , "Plating" ) ;
2019-05-23 08:28:50 -07:00
2018-01-18 11:33:08 -08:00
private static string _applicationTempDataPath = > Path . Combine ( _applicationUserDataPath , "data" , "temp" ) ;
2019-05-23 08:28:50 -07:00
2018-01-18 14:39:59 -08:00
private static string _gcodeOutputPath = > Path . Combine ( _applicationTempDataPath , "gcode" ) ;
2019-05-23 08:28:50 -07:00
2018-07-31 12:21:44 -07:00
private static string _cacheDirectory = > Path . Combine ( _applicationTempDataPath , "cache" ) ;
2018-01-17 22:12:01 -08:00
2019-05-23 08:39:27 -07:00
private static string _printHistoryPath = > Path . Combine ( _applicationLibraryDataPath , "PrintHistory" ) ;
2019-06-06 17:38:52 -07:00
private static string _cloudLibraryPath = > Path . Combine ( _applicationLibraryDataPath , "CloudData" ) ;
2018-01-17 22:07:53 -08:00
public static string ApplicationUserDataPath = > EnsurePath ( _applicationUserDataPath ) ;
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
public string ApplicationLibraryDataPath = > EnsurePath ( _applicationLibraryDataPath ) ;
2018-01-17 21:47:05 -08:00
2019-06-06 17:38:52 -07:00
public string CloudLibraryPath = > EnsurePath ( _cloudLibraryPath ) ;
2018-01-17 22:07:53 -08:00
public string LibraryAssetsPath = > EnsurePath ( _libraryAssetPath ) ;
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
public string ApplicationTempDataPath = > EnsurePath ( _applicationTempDataPath ) ;
public string PlatingDirectory = > EnsurePath ( _platingDirectory ) ;
2018-01-17 22:12:01 -08:00
public string GCodeOutputPath = > EnsurePath ( _gcodeOutputPath ) ;
2018-12-05 16:20:40 -08:00
public string CacheDirectory = > EnsurePath ( _cacheDirectory ) ;
2018-07-31 12:14:33 -07:00
2019-05-23 08:39:27 -07:00
public string PrintHistoryPath = > EnsurePath ( _printHistoryPath ) ;
2018-01-17 22:07:53 -08:00
public string DownloadsDirectory { get ; } = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) , "Downloads" ) ;
2018-01-18 11:51:19 -08:00
public string CustomLibraryFoldersPath = > Path . Combine ( _applicationUserDataPath , "LibraryFolders.conf" ) ;
2018-01-17 22:07:53 -08:00
/// <summary>
2019-05-23 08:28:50 -07:00
/// Gets the path to the Sqlite database
2018-01-17 22:07:53 -08:00
/// </summary>
2019-05-23 08:28:50 -07:00
/// <returns>The path toe Sqlite database</returns>
public string DatastorePath = > Path . Combine ( EnsurePath ( _applicationUserDataPath ) , DatastoreName ) ;
2018-01-17 22:07:53 -08:00
/// <summary>
2019-05-23 08:28:50 -07:00
/// Gets or sets the public storage folder (ex. download folder on Android)
2018-01-17 22:07:53 -08:00
/// </summary>
2018-10-19 15:53:16 -07:00
public string PublicDataStoragePath { get ; set ; }
2018-01-17 21:47:05 -08:00
2018-01-17 22:03:41 -08:00
/// <summary>
/// Invokes CreateDirectory on all paths, creating if missing, before returning
/// </summary>
2019-05-23 08:28:50 -07:00
/// <returns>Returns the path to the given directory</returns>
2018-01-17 22:03:41 -08:00
private static string EnsurePath ( string fullPath )
2018-01-17 21:47:05 -08:00
{
2018-01-17 22:03:41 -08:00
Directory . CreateDirectory ( fullPath ) ;
return fullPath ;
2018-01-17 21:47:05 -08:00
}
/// <summary>
2018-01-17 22:07:53 -08:00
/// Overrides the AppData location. Used by tests to set a non-standard AppData location
2018-01-17 21:47:05 -08:00
/// </summary>
/// <param name="path">The new AppData path.</param>
2019-05-23 08:28:50 -07:00
/// <param name="sqliteBuilder">The Sqlite generator with platform specific bindings</param>
2018-12-18 17:05:53 -08:00
internal void OverrideAppDataLocation ( string path , Func < ISQLite > sqliteBuilder )
2018-01-17 21:47:05 -08:00
{
Console . WriteLine ( " Overriding ApplicationUserDataPath: " + path ) ;
// Ensure the target directory exists
Directory . CreateDirectory ( path ) ;
2018-01-17 22:03:41 -08:00
_applicationUserDataPath = path ;
2018-01-17 21:47:05 -08:00
// Initialize a fresh datastore instance after overriding the AppData path
Datastore . Instance = new Datastore ( ) ;
2018-12-18 17:05:53 -08:00
Datastore . Instance . Initialize ( sqliteBuilder . Invoke ( ) ) ;
2018-01-17 21:47:05 -08:00
}
2018-01-17 22:07:53 -08:00
public string GetTempFileName ( string fileExtension = null )
2018-01-17 21:47:05 -08:00
{
2018-01-17 22:07:53 -08:00
string tempFileName = string . IsNullOrEmpty ( fileExtension ) ?
Path . GetRandomFileName ( ) :
Path . ChangeExtension ( Path . GetRandomFileName ( ) , "." + fileExtension . TrimStart ( '.' ) ) ;
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
return Path . Combine ( this . ApplicationTempDataPath , tempFileName ) ;
}
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
public string GetNewLibraryFilePath ( string extension )
{
string filePath ;
2018-01-17 21:47:05 -08:00
2018-02-06 21:29:20 -08:00
// Force lowercase file extensions
extension = extension . ToLower ( ) ;
2018-01-17 22:07:53 -08:00
// Loop until we've found a non-conflicting library path for the given extension
do
{
filePath = Path . Combine (
_applicationLibraryDataPath ,
Path . ChangeExtension ( Path . GetRandomFileName ( ) , extension ) ) ;
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
} while ( File . Exists ( filePath ) ) ;
2018-01-17 21:47:05 -08:00
2018-01-17 22:07:53 -08:00
return filePath ;
}
2018-01-17 21:47:05 -08:00
}
}