home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipNet.msi / Data1.cab / IsolatedFile.cs < prev    next >
Encoding:
Text File  |  2002-02-05  |  17.0 KB  |  503 lines

  1. /*
  2.  * Xceed Zip for .NET - ExtendingDemo Sample Classes
  3.  * Copyright (c) 2000-2002 - Xceed Software Inc.
  4.  * 
  5.  * [IsolatedFile.cs]
  6.  * 
  7.  * This application demonstrates how to extend the Xceed FileSystem object model by 
  8.  * deriving from the AbstractFile class.
  9.  * 
  10.  * This file is part of Xceed Zip for .NET. The source code in this file 
  11.  * is only intended as a supplement to the documentation, and is provided 
  12.  * "as is", without warranty of any kind, either expressed or implied.
  13.  */
  14.  
  15. using System;
  16. using System.IO;
  17. using System.IO.IsolatedStorage;
  18. using Xceed.FileSystem;
  19.  
  20. namespace Xceed.FileSystem.Samples.ExtendingDemo
  21. {
  22.     /// <summary>
  23.     /// This class demonstrates how to create a class that derives
  24.     /// from the <see cref="AbstractFile"/> class and handles isolated storage files. 
  25.     /// </summary>
  26.     public class IsolatedFile : AbstractFile
  27.     {
  28.     #region PUBLIC CONSTRUCTORS
  29.       
  30.     /// <summary>
  31.     /// Create a new instance of IsolatedFile class.
  32.     /// </summary>
  33.     /// <param name="fileName">Name (with path) of the file.</param>
  34.     /// <remarks><para>
  35.     /// Allowed path: "foo.txt", "foo\bar.txt", "\foo\bar.txt"
  36.     /// </para></remarks>
  37.     public IsolatedFile( string fileName )
  38.     {
  39.       if( fileName == null )
  40.         throw new ArgumentNullException( "fileName" );
  41.       
  42.       fileName = fileName.Trim();
  43.  
  44.       if( fileName.Length == 0 ) 
  45.         throw new ArgumentException( "The file name is empty or contains only whitespace.", "fileName" );
  46.  
  47.       if( fileName.IndexOfAny( this.InvalidChars ) != -1 )
  48.         throw new ArgumentException( "The file name contains invalid characters.", "fileName" );
  49.  
  50.       fileName = fileName.Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar );
  51.  
  52.       if( fileName.EndsWith( Path.DirectorySeparatorChar.ToString() ) )
  53.         throw new ArgumentException( "The fileName is not a file", "fileName" );
  54.   
  55.       fileName = fileName.StartsWith( Path.DirectorySeparatorChar.ToString() ) ? 
  56.         fileName : ( Path.DirectorySeparatorChar + fileName );
  57.  
  58.       m_fullName = fileName;
  59.       m_name     = Path.GetFileName( fileName );
  60.  
  61.       if( m_name.Length == 0 )
  62.         throw new ArgumentException( "The file name represents a folder name.", "fileName" );
  63.     }
  64.       
  65.     #endregion PUBLIC CONSTRUCTORS
  66.  
  67.     #region PRIVATE METHODS
  68.  
  69.     /// <summary>
  70.     /// Gets the size of the file in bytes
  71.     /// </summary>
  72.     /// <returns>A value representing the size of the file in bytes</returns>
  73.     /// <remarks><para>In the case of an exception, -1 is returned.</para></remarks>
  74.     protected override long DoSize
  75.     {
  76.       get
  77.       {
  78.         if( this.Exists )
  79.         {
  80.           try
  81.           {
  82.             IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  83.  
  84.             using( IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream( this.FullName, 
  85.                      FileMode.Open,
  86.                      isoStore ) )
  87.             {
  88.               m_size = isoStream.Length;
  89.             }
  90.           }
  91.           catch( IsolatedStorageException except )
  92.           {
  93.             throw new FileSystemException( "The metadata could not be retrieved from the item.", this, except );
  94.           }
  95.         }
  96.  
  97.         // Return the size of the file in bytes
  98.         return m_size;
  99.       }
  100.     }
  101.  
  102.     /// <summary>
  103.     /// Gets or sets the short name of the file.
  104.     /// </summary>
  105.     /// <value>A string representing the short name of the file.</value>    
  106.     protected override string DoName
  107.     {
  108.       get
  109.       {
  110.         return m_name;
  111.       }
  112.       set
  113.       {
  114.         // You cannot rename a file with the same name but a different 
  115.         // case in a isolated storage.
  116.         if( value == this.Name )
  117.           return;
  118.         
  119.         if( this.Exists )
  120.         {
  121.           // Get a reference to the parent folder of the file and create
  122.           // a new instance of the IsolatedFile class using the path of the parent
  123.           // folder and the new value.
  124.           string path = this.ParentFolder.FullName;
  125.           IsolatedFile file = new IsolatedFile( path + value );
  126.  
  127.           // This will throw ItemAlreadyExistsException if new file exists
  128.           file.Create();
  129.  
  130.           bool moved = false;
  131.           
  132.           // Open the source file for reading and write the contents
  133.           // to the target file.
  134.           try
  135.           {
  136.             using( Stream srcStream = this.OpenRead() )
  137.             {
  138.               using( Stream dstStream = file.OpenWrite( true ) )
  139.               {
  140.                 byte[] buffer = new byte[ ushort.MaxValue ];
  141.                 int bytesRead;
  142.  
  143.                 while( ( bytesRead = srcStream.Read( buffer, 0, buffer.Length ) ) > 0 )
  144.                 {
  145.                   dstStream.Write( buffer, 0, bytesRead );
  146.                 }
  147.               }
  148.             }
  149.  
  150.             // Now that the copy is complete, we delete the original file
  151.             // and refresh our name.
  152.             this.Delete();
  153.   
  154.             moved = true;
  155.           
  156.             m_fullName = file.FullName;
  157.             m_name = file.Name;
  158.           }
  159.           catch( Exception except )
  160.           {
  161.             // Make sure to delete target file if something went wrong.
  162.             if( !moved )
  163.             {
  164.               try
  165.               {
  166.                 file.Delete();
  167.               }
  168.               catch {}
  169.             }
  170.  
  171.             if( except is FileSystemIOException || except is IOException )
  172.               throw new FileSystemException( "An IO exception occured while renaming the item.", this, except );
  173.  
  174.             throw;
  175.           }
  176.         }
  177.         else
  178.         {
  179.           // If the file doesn't exist, we simply need to keep new name.
  180.           m_fullName = this.ParentFolder.FullName + value;
  181.           m_name = value;
  182.         }
  183.       }
  184.     }
  185.  
  186.     /// <summary>
  187.     /// Get the full name of the file.
  188.     /// </summary>
  189.     /// <value>A string that represents the full name of the item.</value>    
  190.     protected override string DoFullName
  191.     {
  192.       get
  193.       {
  194.         return m_fullName;
  195.       }
  196.     }
  197.  
  198.     /// <summary>
  199.     /// Files in isolated storage do not have attributes. Therefore, we throw
  200.     /// a <see cref="FileSystemNotSupportException"/> when trying to get or set the file attributes.
  201.     /// </summary>
  202.     /// <returns><see cref="FileSystemNotSupportException"/></returns>
  203.     protected override FileAttributes DoAttributes
  204.     {
  205.       get
  206.       {
  207.         throw new FileSystemNotSupportedException( this );
  208.       }
  209.       set
  210.       {
  211.         throw new FileSystemNotSupportedException( this );
  212.       }
  213.     }
  214.  
  215.     /// <summary>
  216.     /// Since there is no notion of date/time when dealing with files in 
  217.     /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying
  218.     /// to get or set the CreationDateTime.
  219.     /// </summary>
  220.     /// <returns><see cref="FileSystemNotSupportException"/></returns>
  221.     protected override DateTime DoCreationDateTime
  222.     {
  223.       get
  224.       {
  225.         throw new FileSystemNotSupportedException( this );
  226.       }
  227.       set
  228.       {
  229.         throw new FileSystemNotSupportedException( this );
  230.       }
  231.     }
  232.  
  233.     /// <summary>
  234.     /// Since there is no notion of date/time when dealing with files in 
  235.     /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying
  236.     /// to get or set the LastWriteDateTime.
  237.     /// </summary>
  238.     /// <returns><see cref="FileSystemNotSupportException"/></returns>
  239.     protected override DateTime DoLastWriteDateTime
  240.     {
  241.       get
  242.       {
  243.         throw new FileSystemNotSupportedException( this );
  244.       }
  245.       set
  246.       {
  247.         throw new FileSystemNotSupportedException( this );
  248.       }
  249.     }
  250.  
  251.     /// <summary>
  252.     /// Since there is no notion of date/time when dealing with files in 
  253.     /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying
  254.     /// to get or set the LastAccessDateTime.
  255.     /// </summary>
  256.     /// <returns><see cref="FileSystemNotSupportException"/></returns>
  257.     protected override DateTime DoLastAccessDateTime
  258.     {
  259.       get
  260.       {
  261.         throw new FileSystemNotSupportedException( this );
  262.       }
  263.       set
  264.       {
  265.         throw new FileSystemNotSupportedException( this );
  266.       }
  267.     }
  268.  
  269.     /// <summary>
  270.     /// Gets a reference to the parent folder of the file.
  271.     /// </summary>
  272.     /// <returns>A reference to an <see cref="IsolatedFolder"/> object that represents the folder which 
  273.     /// contains the file, or a null reference if the file does not have a parent.</returns>
  274.     protected override AbstractFolder DoParentFolder
  275.     {
  276.       get
  277.       {
  278.         return new IsolatedFolder( Path.GetDirectoryName( this.FullName ) );
  279.       }
  280.     }
  281.  
  282.     /// <summary>
  283.     /// Gets a reference to the root folder of the file.
  284.     /// </summary>
  285.     /// <returns>A reference to an <see cref="IsolatedFolder"/> object that represents
  286.     /// the root folder of the file.</returns>
  287.     protected override AbstractFolder DoRootFolder
  288.     {
  289.       get
  290.       {
  291.         return new IsolatedFolder( string.Empty );
  292.       }
  293.     }
  294.     
  295.     /// <summary>
  296.     /// Gets a boolean value indicating if the file physically exists.
  297.     /// </summary>
  298.     /// <returns><see langword="true"/> if the item physically exists; <see langword="false"/> otherwise.</returns>
  299.     protected override bool DoExists
  300.     {
  301.       get
  302.       {
  303.         try
  304.         {
  305.           IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  306.  
  307.           return ( isoStore.GetFileNames( this.FullName ).Length != 0 );
  308.         }
  309.         catch( DirectoryNotFoundException )
  310.         {
  311.           return false;
  312.         }
  313.         catch( IsolatedStorageException )
  314.         {
  315.           return false;
  316.         }
  317.       }
  318.     }
  319.  
  320.     /// <summary>
  321.     /// Physically creates the file in the isolated storage.
  322.     /// </summary>
  323.     /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is 
  324.     /// responsible for raising all events that occur during the process.</param>
  325.     protected override void DoCreate( FileSystemEventsSession session )
  326.     {      
  327.       if( this.Exists )
  328.         throw new ItemAlreadyExistsException( this );
  329.  
  330.       // The public Create method is responsible for making sure our parent folder
  331.       // exists. The DoCreate method can assume it's parents exist. We still verify if they do
  332.       // in case something real bad happened.
  333.       if( !this.ParentFolder.Exists )
  334.       {
  335.         System.Diagnostics.Debug.Assert( false, "This case should never happen." );
  336.         throw new FileSystemInternalException( "An unexpected attempt was made to create an item in a folder that does not exist.", this );
  337.       }
  338.  
  339.       try
  340.       {
  341.         IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  342.  
  343.         IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream( this.FullName, 
  344.           FileMode.CreateNew,
  345.           isoStore );
  346.  
  347.         isoStream.Close();
  348.  
  349.         m_size = 0;
  350.       }
  351.       catch( IsolatedStorageException except )
  352.       {
  353.         throw new FileSystemException( "The physical file represented by the item could not be created.", this, except );
  354.       }
  355.     }
  356.  
  357.     /// <summary>
  358.     /// Re-reads the information from the physical file.
  359.     /// </summary>
  360.     protected override void DoRefresh( FileSystemEventsSession session )
  361.     {
  362.       // The Refresh method is documented to throw an exception when the
  363.       // file does not exist. It's our job to check that.
  364.       if( !this.Exists )
  365.         throw new ItemDoesNotExistException( this );
  366.  
  367.       // We have nothing to refresh.     
  368.     }
  369.  
  370.     /// <summary>
  371.     /// Opens the file for reading.
  372.     /// </summary>
  373.     /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is 
  374.     /// responsible for raising all events that occur during the process.</param>
  375.     /// <param name="share">A <see cref="System.IO.FileShare"/> constant that determines how the file will be shared by different processes.</param>
  376.     /// <returns>An <see cref="IsolatedStorageFileStream"/> object that can be used to read data from the file.</returns>
  377.     protected override System.IO.Stream DoOpenRead( FileSystemEventsSession session, FileShare share )
  378.     {
  379.       if( !this.Exists )
  380.         throw new ItemDoesNotExistException( this );
  381.  
  382.       try
  383.       {
  384.         IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  385.   
  386.         // Return an IsolatedStorageFileStream that will be used to read the file's data.
  387.         return new IsolatedStorageFileStream( this.FullName, FileMode.Open, FileAccess.Read, share );
  388.       }
  389.       catch( IsolatedStorageException except )
  390.       {
  391.         throw new FileSystemIOException( "The file item could not be opened for reading.", this, except );
  392.       }
  393.     }
  394.  
  395.     /// <summary>
  396.     /// Opens the file for writing.
  397.     /// </summary>
  398.     /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is 
  399.     /// responsible for raising all events that occur during the process. </param>
  400.     /// <param name="overwrite"><see langword="true"/> if existing data for the file should be replaced; <see langword="false"/> if existing data should be 
  401.     /// preserved, appending new data at the end.</param>
  402.     /// <param name="share">A <see cref="System.IO.FileShare"/> constant that determines how the file will be shared by different processes.</param>
  403.     /// <returns>An <see cref="IsolatedStorageFileStream"/> object that can be used to write data to the file.</returns>
  404.     protected override System.IO.Stream DoOpenWrite( FileSystemEventsSession session, bool overwrite, 
  405.                                                      FileShare share )
  406.     {
  407.       if( !this.Exists )
  408.         throw new ItemDoesNotExistException( this );
  409.  
  410.       try
  411.       {
  412.         IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  413.  
  414.         // Return an IsolatedStorageFileStream that will be used to write data to the file.
  415.         // If the overwrite parameter is set to true, the entire contents of the existing file
  416.         // will be overwritten. Otherwise, the data will be appended to the existing data.
  417.         if( overwrite )
  418.           return new IsolatedStorageFileStream( this.FullName, FileMode.Create, FileAccess.Write, share );
  419.         else
  420.           return new IsolatedStorageFileStream( this.FullName, FileMode.Append, FileAccess.Write, share );
  421.       }
  422.       catch( IsolatedStorageException except )
  423.       {
  424.         throw new FileSystemIOException( "The file item could not be opened for writing.", this, except );
  425.       }
  426.     }
  427.     
  428.     /// <summary>
  429.     /// Gets a boolean value indicating if the source and target items are the same.
  430.     /// </summary>
  431.     /// <param name="target">A <see cref="FileSystemItem"/> object representing the destination file.</param>
  432.     /// <returns><see langword="true"/> if the source and target <see cref="FileSystemItem"/> objects are the same; <see langword="false"/> otherwise.</returns>
  433.     protected override bool IsSameAs( FileSystemItem target )
  434.     {
  435.       if( target == null )
  436.         return false;
  437.  
  438.       // In some file systems, two identical filenames does not mean
  439.       // it's the same file. With the isolated storage's domain store,
  440.       // we can simply check if both items have the same type and fullname.
  441.       if( target is IsolatedFile )
  442.       {
  443.         return( this.FullName == target.FullName );
  444.       }
  445.       else
  446.       {
  447.         return false;
  448.       }
  449.     }
  450.  
  451.     /// <summary>
  452.     /// Returns a boolean value indicating if the path passed is rooted in the 
  453.     /// isolated storage environment.
  454.     /// </summary>
  455.     /// <param name="path">The path to verify</param>
  456.     /// <returns><see langword="true"/> if the path is rooted; <see langword="false"/> otherwise.</returns>
  457.     protected override bool IsPathRooted( string path )
  458.     {
  459.       return false;
  460.     }
  461.     
  462.     /// <summary>
  463.     /// Permanently deletes the file.
  464.     /// </summary>
  465.     /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is responsible for raising all 
  466.     /// events that occur during the process.</param>
  467.     protected override void DoDelete( FileSystemEventsSession session )
  468.     {      
  469.       if( !this.Exists )
  470.         throw new ItemDoesNotExistException( this );
  471.  
  472.       try
  473.       {
  474.         IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore;
  475.  
  476.         isoStore.DeleteFile( this.FullName );
  477.       
  478.         m_size = 0;
  479.       }
  480.       catch( IsolatedStorageException except )
  481.       {
  482.         throw new FileSystemException( "The item could not be deleted.", this, except );
  483.       }
  484.     }
  485.  
  486.     #endregion PRIVATE METHODS
  487.     
  488.     #region PRIVATE FIELDS
  489.    
  490.  
  491.     // The short name of the file.
  492.     private string m_name = string.Empty;
  493.  
  494.     // The full name of the file.
  495.     private string m_fullName = string.Empty;
  496.  
  497.     // The size of the file.
  498.     private long m_size = 0;
  499.     
  500.     #endregion PRIVATE FIELDS     
  501.     }
  502. }
  503.