home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * Xceed Zip for .NET - ExtendingDemo Sample Classes * Copyright (c) 2000-2002 - Xceed Software Inc. * * [IsolatedFile.cs] * * This application demonstrates how to extend the Xceed FileSystem object model by * deriving from the AbstractFile class. * * This file is part of Xceed Zip for .NET. The source code in this file * is only intended as a supplement to the documentation, and is provided * "as is", without warranty of any kind, either expressed or implied. */ using System; using System.IO; using System.IO.IsolatedStorage; using Xceed.FileSystem; namespace Xceed.FileSystem.Samples.ExtendingDemo { /// <summary> /// This class demonstrates how to create a class that derives /// from the <see cref="AbstractFile"/> class and handles isolated storage files. /// </summary> public class IsolatedFile : AbstractFile { #region PUBLIC CONSTRUCTORS /// <summary> /// Create a new instance of IsolatedFile class. /// </summary> /// <param name="fileName">Name (with path) of the file.</param> /// <remarks><para> /// Allowed path: "foo.txt", "foo\bar.txt", "\foo\bar.txt" /// </para></remarks> public IsolatedFile( string fileName ) { if( fileName == null ) throw new ArgumentNullException( "fileName" ); fileName = fileName.Trim(); if( fileName.Length == 0 ) throw new ArgumentException( "The file name is empty or contains only whitespace.", "fileName" ); if( fileName.IndexOfAny( this.InvalidChars ) != -1 ) throw new ArgumentException( "The file name contains invalid characters.", "fileName" ); fileName = fileName.Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar ); if( fileName.EndsWith( Path.DirectorySeparatorChar.ToString() ) ) throw new ArgumentException( "The fileName is not a file", "fileName" ); fileName = fileName.StartsWith( Path.DirectorySeparatorChar.ToString() ) ? fileName : ( Path.DirectorySeparatorChar + fileName ); m_fullName = fileName; m_name = Path.GetFileName( fileName ); if( m_name.Length == 0 ) throw new ArgumentException( "The file name represents a folder name.", "fileName" ); } #endregion PUBLIC CONSTRUCTORS #region PRIVATE METHODS /// <summary> /// Gets the size of the file in bytes /// </summary> /// <returns>A value representing the size of the file in bytes</returns> /// <remarks><para>In the case of an exception, -1 is returned.</para></remarks> protected override long DoSize { get { if( this.Exists ) { try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; using( IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream( this.FullName, FileMode.Open, isoStore ) ) { m_size = isoStream.Length; } } catch( IsolatedStorageException except ) { throw new FileSystemException( "The metadata could not be retrieved from the item.", this, except ); } } // Return the size of the file in bytes return m_size; } } /// <summary> /// Gets or sets the short name of the file. /// </summary> /// <value>A string representing the short name of the file.</value> protected override string DoName { get { return m_name; } set { // You cannot rename a file with the same name but a different // case in a isolated storage. if( value == this.Name ) return; if( this.Exists ) { // Get a reference to the parent folder of the file and create // a new instance of the IsolatedFile class using the path of the parent // folder and the new value. string path = this.ParentFolder.FullName; IsolatedFile file = new IsolatedFile( path + value ); // This will throw ItemAlreadyExistsException if new file exists file.Create(); bool moved = false; // Open the source file for reading and write the contents // to the target file. try { using( Stream srcStream = this.OpenRead() ) { using( Stream dstStream = file.OpenWrite( true ) ) { byte[] buffer = new byte[ ushort.MaxValue ]; int bytesRead; while( ( bytesRead = srcStream.Read( buffer, 0, buffer.Length ) ) > 0 ) { dstStream.Write( buffer, 0, bytesRead ); } } } // Now that the copy is complete, we delete the original file // and refresh our name. this.Delete(); moved = true; m_fullName = file.FullName; m_name = file.Name; } catch( Exception except ) { // Make sure to delete target file if something went wrong. if( !moved ) { try { file.Delete(); } catch {} } if( except is FileSystemIOException || except is IOException ) throw new FileSystemException( "An IO exception occured while renaming the item.", this, except ); throw; } } else { // If the file doesn't exist, we simply need to keep new name. m_fullName = this.ParentFolder.FullName + value; m_name = value; } } } /// <summary> /// Get the full name of the file. /// </summary> /// <value>A string that represents the full name of the item.</value> protected override string DoFullName { get { return m_fullName; } } /// <summary> /// Files in isolated storage do not have attributes. Therefore, we throw /// a <see cref="FileSystemNotSupportException"/> when trying to get or set the file attributes. /// </summary> /// <returns><see cref="FileSystemNotSupportException"/></returns> protected override FileAttributes DoAttributes { get { throw new FileSystemNotSupportedException( this ); } set { throw new FileSystemNotSupportedException( this ); } } /// <summary> /// Since there is no notion of date/time when dealing with files in /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying /// to get or set the CreationDateTime. /// </summary> /// <returns><see cref="FileSystemNotSupportException"/></returns> protected override DateTime DoCreationDateTime { get { throw new FileSystemNotSupportedException( this ); } set { throw new FileSystemNotSupportedException( this ); } } /// <summary> /// Since there is no notion of date/time when dealing with files in /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying /// to get or set the LastWriteDateTime. /// </summary> /// <returns><see cref="FileSystemNotSupportException"/></returns> protected override DateTime DoLastWriteDateTime { get { throw new FileSystemNotSupportedException( this ); } set { throw new FileSystemNotSupportedException( this ); } } /// <summary> /// Since there is no notion of date/time when dealing with files in /// isolate storage, we throw a <see cref="FileSystemNotSupportException"/> when trying /// to get or set the LastAccessDateTime. /// </summary> /// <returns><see cref="FileSystemNotSupportException"/></returns> protected override DateTime DoLastAccessDateTime { get { throw new FileSystemNotSupportedException( this ); } set { throw new FileSystemNotSupportedException( this ); } } /// <summary> /// Gets a reference to the parent folder of the file. /// </summary> /// <returns>A reference to an <see cref="IsolatedFolder"/> object that represents the folder which /// contains the file, or a null reference if the file does not have a parent.</returns> protected override AbstractFolder DoParentFolder { get { return new IsolatedFolder( Path.GetDirectoryName( this.FullName ) ); } } /// <summary> /// Gets a reference to the root folder of the file. /// </summary> /// <returns>A reference to an <see cref="IsolatedFolder"/> object that represents /// the root folder of the file.</returns> protected override AbstractFolder DoRootFolder { get { return new IsolatedFolder( string.Empty ); } } /// <summary> /// Gets a boolean value indicating if the file physically exists. /// </summary> /// <returns><see langword="true"/> if the item physically exists; <see langword="false"/> otherwise.</returns> protected override bool DoExists { get { try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; return ( isoStore.GetFileNames( this.FullName ).Length != 0 ); } catch( DirectoryNotFoundException ) { return false; } catch( IsolatedStorageException ) { return false; } } } /// <summary> /// Physically creates the file in the isolated storage. /// </summary> /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is /// responsible for raising all events that occur during the process.</param> protected override void DoCreate( FileSystemEventsSession session ) { if( this.Exists ) throw new ItemAlreadyExistsException( this ); // The public Create method is responsible for making sure our parent folder // exists. The DoCreate method can assume it's parents exist. We still verify if they do // in case something real bad happened. if( !this.ParentFolder.Exists ) { System.Diagnostics.Debug.Assert( false, "This case should never happen." ); throw new FileSystemInternalException( "An unexpected attempt was made to create an item in a folder that does not exist.", this ); } try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream( this.FullName, FileMode.CreateNew, isoStore ); isoStream.Close(); m_size = 0; } catch( IsolatedStorageException except ) { throw new FileSystemException( "The physical file represented by the item could not be created.", this, except ); } } /// <summary> /// Re-reads the information from the physical file. /// </summary> protected override void DoRefresh( FileSystemEventsSession session ) { // The Refresh method is documented to throw an exception when the // file does not exist. It's our job to check that. if( !this.Exists ) throw new ItemDoesNotExistException( this ); // We have nothing to refresh. } /// <summary> /// Opens the file for reading. /// </summary> /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is /// responsible for raising all events that occur during the process.</param> /// <param name="share">A <see cref="System.IO.FileShare"/> constant that determines how the file will be shared by different processes.</param> /// <returns>An <see cref="IsolatedStorageFileStream"/> object that can be used to read data from the file.</returns> protected override System.IO.Stream DoOpenRead( FileSystemEventsSession session, FileShare share ) { if( !this.Exists ) throw new ItemDoesNotExistException( this ); try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; // Return an IsolatedStorageFileStream that will be used to read the file's data. return new IsolatedStorageFileStream( this.FullName, FileMode.Open, FileAccess.Read, share ); } catch( IsolatedStorageException except ) { throw new FileSystemIOException( "The file item could not be opened for reading.", this, except ); } } /// <summary> /// Opens the file for writing. /// </summary> /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is /// responsible for raising all events that occur during the process. </param> /// <param name="overwrite"><see langword="true"/> if existing data for the file should be replaced; <see langword="false"/> if existing data should be /// preserved, appending new data at the end.</param> /// <param name="share">A <see cref="System.IO.FileShare"/> constant that determines how the file will be shared by different processes.</param> /// <returns>An <see cref="IsolatedStorageFileStream"/> object that can be used to write data to the file.</returns> protected override System.IO.Stream DoOpenWrite( FileSystemEventsSession session, bool overwrite, FileShare share ) { if( !this.Exists ) throw new ItemDoesNotExistException( this ); try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; // Return an IsolatedStorageFileStream that will be used to write data to the file. // If the overwrite parameter is set to true, the entire contents of the existing file // will be overwritten. Otherwise, the data will be appended to the existing data. if( overwrite ) return new IsolatedStorageFileStream( this.FullName, FileMode.Create, FileAccess.Write, share ); else return new IsolatedStorageFileStream( this.FullName, FileMode.Append, FileAccess.Write, share ); } catch( IsolatedStorageException except ) { throw new FileSystemIOException( "The file item could not be opened for writing.", this, except ); } } /// <summary> /// Gets a boolean value indicating if the source and target items are the same. /// </summary> /// <param name="target">A <see cref="FileSystemItem"/> object representing the destination file.</param> /// <returns><see langword="true"/> if the source and target <see cref="FileSystemItem"/> objects are the same; <see langword="false"/> otherwise.</returns> protected override bool IsSameAs( FileSystemItem target ) { if( target == null ) return false; // In some file systems, two identical filenames does not mean // it's the same file. With the isolated storage's domain store, // we can simply check if both items have the same type and fullname. if( target is IsolatedFile ) { return( this.FullName == target.FullName ); } else { return false; } } /// <summary> /// Returns a boolean value indicating if the path passed is rooted in the /// isolated storage environment. /// </summary> /// <param name="path">The path to verify</param> /// <returns><see langword="true"/> if the path is rooted; <see langword="false"/> otherwise.</returns> protected override bool IsPathRooted( string path ) { return false; } /// <summary> /// Permanently deletes the file. /// </summary> /// <param name="session">A reference to a <see cref="FileSystemEventsSession"/> object which is responsible for raising all /// events that occur during the process.</param> protected override void DoDelete( FileSystemEventsSession session ) { if( !this.Exists ) throw new ItemDoesNotExistException( this ); try { IsolatedStorageFile isoStore = IsolatedFolder.m_domainStore; isoStore.DeleteFile( this.FullName ); m_size = 0; } catch( IsolatedStorageException except ) { throw new FileSystemException( "The item could not be deleted.", this, except ); } } #endregion PRIVATE METHODS #region PRIVATE FIELDS // The short name of the file. private string m_name = string.Empty; // The full name of the file. private string m_fullName = string.Empty; // The size of the file. private long m_size = 0; #endregion PRIVATE FIELDS } }