crashanalysercmd/Libraries/Engine/CrashItemLib/Sink/CISinkSerializationParameters.cs
changeset 0 818e61de6cd1
child 2 0c91f0baec58
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Text;
       
    19 using System.IO;
       
    20 using System.Collections.Generic;
       
    21 using System.Reflection;
       
    22 using System.ComponentModel;
       
    23 using SymbianUtils;
       
    24 using SymbianDebugLib.Engine;
       
    25 using CrashItemLib.Crash;
       
    26 using CrashItemLib.Crash.Container;
       
    27 using CrashItemLib.PluginAPI;
       
    28 using CrashItemLib.Engine;
       
    29 using SymbianUtils.FileSystem.Utilities;
       
    30 
       
    31 namespace CrashItemLib.Sink
       
    32 {
       
    33     public class CISinkSerializationParameters : DisposableObject
       
    34     {
       
    35         #region Enumerations
       
    36         public enum TDetailLevel
       
    37         {
       
    38             [Description("Full")]
       
    39             EFull = 0,
       
    40 
       
    41             [Description( "Summary" )]
       
    42             ESummary
       
    43         }
       
    44         #endregion
       
    45 
       
    46         #region Constructors
       
    47         public CISinkSerializationParameters( Version aUIVersion, string aUICommandLineArguments )
       
    48         {
       
    49             iUIVersion = aUIVersion;
       
    50             iUICommandLineArguments = aUICommandLineArguments;
       
    51             //
       
    52             string tempPath = FSUtilities.MakeTempPath();
       
    53             OutputDirectory = new DirectoryInfo( tempPath );
       
    54             //
       
    55             PrepareDefaultExtensions();
       
    56         }
       
    57         
       
    58         public CISinkSerializationParameters( CIContainer aContainer, Version aUIVersion, string aUICommandLineArguments )
       
    59             : this( aUIVersion, aUICommandLineArguments )
       
    60         {
       
    61             iContainer = aContainer;
       
    62         }
       
    63 
       
    64         public CISinkSerializationParameters( CISinkSerializationParameters aCopy )
       
    65             : this( aCopy.Container, aCopy.UIVersion, aCopy.UICommandLineArguments )
       
    66         {
       
    67             iDetailLevel = aCopy.DetailLevel;
       
    68             //
       
    69             FileExtensionSuccess = aCopy.FileExtensionSuccess;
       
    70             FileExtensionFailed = aCopy.FileExtensionFailed;
       
    71             //
       
    72             if ( aCopy.iOutputMode == TOutputMode.EOutputToFile )
       
    73             {
       
    74                 OutputFile = aCopy.OutputFile;
       
    75             }
       
    76             else if ( aCopy.iOutputMode == TOutputMode.EOutputToDirectory )
       
    77             {
       
    78                 OutputDirectory = aCopy.OutputDirectory;
       
    79             }
       
    80             //
       
    81             iOperationData1 = aCopy.OperationData1;
       
    82             iOperationData2 = aCopy.OperationData2;
       
    83             iOperationData3 = aCopy.OperationData3;
       
    84         }
       
    85         #endregion
       
    86 
       
    87         #region API
       
    88         public Stream CreateFile( out string aFileName )
       
    89         {
       
    90             return CreateFile( out aFileName, FileMode.Append );
       
    91         }
       
    92 
       
    93         public Stream CreateFile( out string aFileName, FileMode aMode )
       
    94         {
       
    95             System.Diagnostics.Debug.Assert( iContainer != null );
       
    96 
       
    97             // First, prepare the output directory information that we will write to.
       
    98             string fileName = Container.Source.MasterFileName;
       
    99             string sourceFileName = Path.GetFileName( fileName );
       
   100             string sourcePath = Path.GetDirectoryName( fileName );
       
   101             //
       
   102             switch ( iOutputMode )
       
   103             {
       
   104             case TOutputMode.EOutputToDirectory:
       
   105                 // Use the OutputDirectory name, but combine with source file name
       
   106                 fileName = Path.Combine( this.OutputDirectory.FullName, sourceFileName );
       
   107                 fileName = AppendFileExtension( fileName );
       
   108 
       
   109                 // Don't overwrite when writing to a specific directory.
       
   110                 aMode = FileMode.CreateNew;
       
   111                 break;
       
   112             default:
       
   113             case TOutputMode.EOutputToFile:
       
   114                 // Use the specified OuputFile name.
       
   115                 fileName = this.OutputFile.FullName;
       
   116                 break;
       
   117             }
       
   118 
       
   119             // At this point we now have a fixed output path.
       
   120             // Ensure that it exists.
       
   121             DirectoryInfo outputDir = new DirectoryInfo( Path.GetDirectoryName( fileName ) );
       
   122             outputDir.Create();
       
   123 
       
   124             // Now try to make a unique file name if we are not appending.
       
   125             Stream ret = null;
       
   126             if ( aMode == FileMode.Append )
       
   127             {
       
   128                 // Just append to file
       
   129                 ret = TryToCreateStream( fileName, aMode );
       
   130             }
       
   131             else
       
   132             {
       
   133                 // Update filename to just refer to the name and extension (no path)
       
   134                 fileName = Path.GetFileName( fileName );
       
   135 
       
   136                 // Try to create a unique file
       
   137                 for ( int counter = 0; counter < KMaxRetries; counter++ )
       
   138                 {
       
   139                     // First iteration is a special case were we use input name
       
   140                     // plus our standard extension
       
   141                     string finalFileName = AppendFileExtension( fileName );
       
   142                     if ( counter > 0 )
       
   143                     {
       
   144                         // Append a numerical value in order to create unique name
       
   145                         finalFileName = string.Format( "{0} ({1:d3})",
       
   146                                             Path.GetFileNameWithoutExtension( fileName ),
       
   147                                             counter );
       
   148                         finalFileName = AppendFileExtension( finalFileName );
       
   149                     }
       
   150 
       
   151                     string finalFullName = Path.Combine( outputDir.FullName, finalFileName );
       
   152  
       
   153                     // Attempt to create stream
       
   154                     ret = TryToCreateStream( finalFullName, aMode );
       
   155                     if ( ret != null )
       
   156                     {
       
   157                         fileName = finalFullName;
       
   158                         break;
       
   159                     }
       
   160                 }
       
   161             }
       
   162 
       
   163             //
       
   164             if ( ret == null )
       
   165             {
       
   166                 throw new IOException( "Unable to create sink file" );
       
   167             }
       
   168             else
       
   169             {
       
   170                 // Ensure we inform caller of final output file name
       
   171                 aFileName = fileName;
       
   172             }
       
   173             //
       
   174             return ret;
       
   175         }
       
   176         #endregion
       
   177 
       
   178         #region Framework API
       
   179         protected virtual void PrepareDefaultExtensions()
       
   180         {
       
   181             FileExtensionSuccess = string.Empty;
       
   182             FileExtensionFailed = string.Empty;
       
   183         }
       
   184         #endregion
       
   185 
       
   186         #region Properties
       
   187         public CIEngine Engine
       
   188         {
       
   189             get { return Container.Engine; }
       
   190         }
       
   191 
       
   192         public CIContainer Container
       
   193         {
       
   194             get { return iContainer; }
       
   195             set { iContainer = value; }
       
   196         }
       
   197 
       
   198         public TDetailLevel DetailLevel
       
   199         {
       
   200             get { return iDetailLevel; }
       
   201             set { iDetailLevel = value; }
       
   202         }
       
   203 
       
   204         public DirectoryInfo OutputDirectory
       
   205         {
       
   206             get
       
   207             {
       
   208                 if ( iOutputMode != TOutputMode.EOutputToDirectory )
       
   209                 {
       
   210                     throw new InvalidOperationException( "Output mode is invalid" );
       
   211                 }
       
   212                 return iOutputDirectory;
       
   213             }
       
   214             set
       
   215             {
       
   216                 iOutputDirectory = value;
       
   217                 iOutputDirectory.Create();
       
   218                 //
       
   219                 iOutputMode = TOutputMode.EOutputToDirectory;
       
   220                 iOutputFile = null;
       
   221             }
       
   222         }
       
   223 
       
   224         public FileInfo OutputFile
       
   225         {
       
   226             get
       
   227             {
       
   228                 if ( iOutputMode != TOutputMode.EOutputToFile )
       
   229                 {
       
   230                     throw new InvalidOperationException( "Output mode is invalid" );
       
   231                 }
       
   232                 return iOutputFile; 
       
   233             }
       
   234             set
       
   235             {
       
   236                 iOutputFile = value;
       
   237                 //
       
   238                 iOutputMode = TOutputMode.EOutputToFile;
       
   239                 iOutputDirectory = null;
       
   240             }
       
   241         }
       
   242 
       
   243         public Version UIVersion
       
   244         {
       
   245             get { return iUIVersion; }
       
   246         }
       
   247 
       
   248         public string FileExtensionSuccess
       
   249         {
       
   250             get { return iFileExtensionSuccess; }
       
   251             set { iFileExtensionSuccess = value; }
       
   252         }
       
   253 
       
   254         public string FileExtensionFailed
       
   255         {
       
   256             get { return iFileExtensionFailed; }
       
   257             set { iFileExtensionFailed = value; }
       
   258         }
       
   259 
       
   260         public string UICommandLineArguments
       
   261         {
       
   262             get { return iUICommandLineArguments; }
       
   263         }
       
   264 
       
   265         public object OperationData1
       
   266         {
       
   267             get { return iOperationData1; }
       
   268             set { iOperationData1 = value; }
       
   269         }
       
   270 
       
   271         public object OperationData2
       
   272         {
       
   273             get { return iOperationData2; }
       
   274             set { iOperationData2 = value; }
       
   275         }
       
   276 
       
   277         public object OperationData3
       
   278         {
       
   279             get { return iOperationData3; }
       
   280             set { iOperationData3 = value; }
       
   281         }
       
   282         #endregion
       
   283 
       
   284         #region Internal methods
       
   285         private string AppendFileExtension( string aFileName )
       
   286         {
       
   287             System.Diagnostics.Debug.Assert( iContainer != null );
       
   288             
       
   289             // Work out which extension we should be adding to the output
       
   290             string extensionToAppend = FileExtensionSuccess;
       
   291             if ( Container.Status == CIContainer.TStatus.EStatusErrorContainer )
       
   292             {
       
   293                 extensionToAppend = FileExtensionFailed;
       
   294             }
       
   295 
       
   296             // Then make the name
       
   297             string ret = aFileName;
       
   298             string extn = Path.GetExtension( aFileName );
       
   299             //
       
   300             if ( extn.ToUpper() == extensionToAppend.ToUpper() )
       
   301             {
       
   302                 // Job done
       
   303             }
       
   304             else
       
   305             {
       
   306                 ret += extensionToAppend;
       
   307             }
       
   308             //
       
   309             return ret;
       
   310         }
       
   311 
       
   312         private Stream TryToCreateStream( string aFileName, FileMode aMode )
       
   313         {
       
   314             Stream ret = null;
       
   315             //
       
   316             try
       
   317             {
       
   318                 // We do this inside a catch block because in multi-threaded situations, there
       
   319                 // could be a race between the entity checking whether a file exists, and another
       
   320                 // thread actually just about to create the file. The File.Exists() check just
       
   321                 // avoids unnecessarily attempting to create the file if we *know* that it already
       
   322                 // exists. The catch copes with the unexpected pre-emption.
       
   323                 if ( !File.Exists( aFileName ) )
       
   324                 {
       
   325                     ret = new FileStream( aFileName, aMode, FileAccess.Write, FileShare.None, 1024 * 12 );
       
   326                 }
       
   327             }
       
   328             catch ( IOException )
       
   329             {
       
   330             }
       
   331             //
       
   332             return ret;
       
   333         }
       
   334         #endregion
       
   335 
       
   336         #region Internal constants
       
   337         private const int KMaxRetries = 100;
       
   338         #endregion
       
   339 
       
   340         #region Internal enumerations
       
   341         private enum TOutputMode
       
   342         {
       
   343             EOutputToFile = 0,
       
   344             EOutputToDirectory
       
   345         }
       
   346         #endregion
       
   347 
       
   348         #region Data members
       
   349         private readonly Version iUIVersion;
       
   350         private readonly string iUICommandLineArguments;
       
   351         private CIContainer iContainer;
       
   352         private TDetailLevel iDetailLevel = TDetailLevel.EFull;
       
   353         private string iFileExtensionSuccess = string.Empty;
       
   354         private string iFileExtensionFailed = string.Empty;
       
   355         private FileInfo iOutputFile;
       
   356         private DirectoryInfo iOutputDirectory;
       
   357         private TOutputMode iOutputMode = TOutputMode.EOutputToDirectory;
       
   358         private object iOperationData1 = null;
       
   359         private object iOperationData2 = null;
       
   360         private object iOperationData3 = null;
       
   361         #endregion
       
   362     }
       
   363 }