crashanalysercmd/UI/Plugins/CAPluginCrashAnalyser/CommandLine/Inputs/CACmdLineInputParameters.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
* 
* Description:
*
*/
using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
using CrashAnalyserEngine.Plugins;
using CrashItemLib.Engine;
using CrashItemLib.Crash;
using CrashItemLib.Crash.Container;
using CrashItemLib.PluginAPI;
using CrashAnalyserEngine.Engine;
using CrashAnalyserEngine.Interfaces;
using CAPCrashAnalysis.Plugin;
using SymbianUtils.FileSystem.Utilities;
using SymbianXmlInputLib.Parser;
using SymbianXmlInputLib.Parser.Nodes;
using SymbianXmlInputLib.Elements;
using SymbianXmlInputLib.Elements.Types.Category;
using SymbianXmlInputLib.Elements.Types.Extension;
using SymbianXmlInputLib.Elements.Types.FileSystem;
using SymbianXmlInputLib.Elements.Types.Command;
using CrashItemLib.Sink;

namespace CAPCrashAnalysis.CommandLine
{
	internal class CACmdLineInputParameters
	{
		#region Constructors
        public CACmdLineInputParameters( CAPluginCrashAnalysis aEngine )
		{
            iEngine = aEngine;
            //
            Version version = aEngine.UIManager.UIVersion;
            string commandLine = aEngine.UIManager.UICommandLineArguments;
            //
            iSinkParams = new CISinkSerializationParameters( version, commandLine );
		}
		#endregion

		#region API
        public void Read( string aFileName )
        {
            Trace( "[CmdInput] Read() - aFileName: " + aFileName );
            try
            {
                // First create the tree
                SXILDocument doc = CreateDocumentTree( aFileName );

                // Then convert it to the list of elements that we care about
                ExtractData( doc );
            }
            catch ( CACmdLineException cmdLineException )
            {
                Trace( "[CmdInput] Read() - CACmdLineException: " + cmdLineException.Message + " " + cmdLineException.StackTrace );
                throw cmdLineException;
            }
            catch ( Exception generalException )
            {
                Trace( "[CmdInput] Read() - generalException: " + generalException.Message + " " + generalException.StackTrace );
                throw new CACmdLineException( "Error reading input xml file", generalException, CAPlugin.KErrCommandLinePluginArgumentsFileInvalid );
            }
            Trace( "[CmdInput] Read() - read OK: " + aFileName );
        }
        #endregion

		#region Properties
        public CISinkSerializationParameters SinkParameters
        {
            get { return iSinkParams; }
        }

        public CACmdLineFSEntityList<CACmdLineFileSource> SourceFiles
        {
            get { return iSources; }
        }

        public CACmdLineFSEntityList<CACmdLineFSEntity> MetaDataFiles
        {
            get { return iMetaData; }
        }
        #endregion

        #region Internal constants
        private const string KInputFileDocumentRootNode = "crash_analysis";
        private const string KInputFileCategorySource = "source";
        private const string KInputFileCategoryDebugMetaData = "debug_meta_data";
        private const string KInputFileCategoryParameters = "parameters";
        private const string KInputFileCategoryOutput = "output";
        private const string KInputFileCommandNameAnalysis = "analysis_type";
        private const string KInputFileCommandNameAnalysisFull = "FULL";
        private const string KInputFileCommandNameAnalysisSummary = "SUMMARY";
        #endregion

        #region Internal methods
        private SXILDocument CreateDocumentTree( string aFileName )
        {
            SXILDocument doc = new SXILDocument();

            // Read input file into document
            using ( SXILParser parser = new SXILParser( aFileName, KInputFileDocumentRootNode, doc ) )
            {
                parser.CategoryAdd( KInputFileCategorySource, new SXILParserNodeFileSystem() );
                parser.CategoryAdd( KInputFileCategoryDebugMetaData, new SXILParserNodeFileSystem() );
                parser.CategoryAdd( KInputFileCategoryParameters,
                    new SXILParserNodeCommand(),
                    new SXILParserNodeExtension()
                    );
                parser.CategoryAdd( KInputFileCategoryOutput, new SXILParserNodeFileSystem() );
                parser.Parse();
            }

            return doc;
        }

        private void ExtractData( SXILDocument aDocument )
        {
            foreach ( SXILElement element in aDocument )
            {
                if ( element is SXILElementCategory )
                {
                    SXILElementCategory category = (SXILElementCategory) element;
                    string name = category.Name.ToLower();
                    //
                    switch ( name )
                    {
                    case KInputFileCategorySource:
                        ExtractFileList<CACmdLineFileSource>( iSources, category );
                        break;
                    case KInputFileCategoryDebugMetaData:
                        // The debug meta data engine doesn't support directories anymore
                        // so we have to expand all directories to files.
                        ExtractFileList<CACmdLineFSEntity>( iMetaData, category );
                        break;
                    case KInputFileCategoryParameters:
                        ExtractParameters( category );
                        break;
                    case KInputFileCategoryOutput:
                        ExtractOutput( category );
                        break;
                    }
                }
            }

            // We don't require debug meta data if performing a summary operation. Otherwise, we do.
            if ( iMetaData.Count == 0 && iSinkParams.DetailLevel == CISinkSerializationParameters.TDetailLevel.EFull )
            {
                Trace( "[CmdInput] ExtractData() - WARNING - no debug meta data supplied for full analysis." );
            }
        
        }

        private void ExtractFileList<T>( CACmdLineFSEntityList<T> aList, SXILElementCategory aCategory ) where T : CACmdLineFSEntity, new()
        {
            foreach ( SXILElement element in aCategory )
            {
                if ( element is SXILElementFile )
                {
                    SXILElementFile file = (SXILElementFile) element;
                    Trace( "[CmdInput] ExtractFileList() - file: " + file );
                    if ( !file.Exists )
                    {
                        throw new FileNotFoundException( "File not found", file.Name );
                    }
                    //
                    aList.Add( file );
                }
                else if ( element is SXILElementDirectory )
                {
                    SXILElementDirectory dir = (SXILElementDirectory) element;
                    Trace( "[CmdInput] ExtractFileList() - dir:  " + dir );
                    if ( !dir.Exists )
                    {
                        throw new DirectoryNotFoundException( "Directory not found: " + dir.Name );
                    }
                    //
                    aList.AddRange( dir.Files );
                }
            }
        }

        private void ExtractParameters( SXILElementCategory aCategory )
        {
            foreach ( SXILElement element in aCategory )
            {
                if ( element is SXILElementExtension )
                {
                    SXILElementExtension entry = (SXILElementExtension) element;
                    //
                    string extension = entry.Name;
                    if ( !extension.StartsWith( "." ) )
                    {
                        extension = "." + extension;
                    }
                    //
                    if ( entry.Type == SXILElementExtension.TType.ETypeFailure )
                    {
                        Trace( "[CmdInput] ExtractFileList() - failed extension: " + extension );
                        iSinkParams.FileExtensionFailed = extension;
                    }
                    else if ( entry.Type == SXILElementExtension.TType.ETypeSuccess )
                    {
                        Trace( "[CmdInput] ExtractFileList() - success extension: " + extension );
                        iSinkParams.FileExtensionSuccess = extension;
                    }
                }
                else if ( element is SXILElementCommand )
                {
                    SXILElementCommand entry = (SXILElementCommand) element;
                    //
                    if ( entry.Name == KInputFileCommandNameAnalysis )
                    {
                        string type = entry.Details.Trim().ToUpper();
                        Trace( "[CmdInput] ExtractFileList() - command: " + type );
                        switch ( type )
                        {
                        case KInputFileCommandNameAnalysisFull:
                            iSinkParams.DetailLevel = CISinkSerializationParameters.TDetailLevel.EFull;
                            break;
                        case KInputFileCommandNameAnalysisSummary:
                            iSinkParams.DetailLevel = CISinkSerializationParameters.TDetailLevel.ESummary;
                            break;
                        default:
                            throw new NotSupportedException( "Unsupported analysis type" );
                        }
                    }
                    else
                    {
                        throw new NotSupportedException( "Unsupported command: " + entry.Name );
                    }
                }
            }
        }

        private void ExtractOutput( SXILElementCategory aCategory )
        {
            // We either output to file or directory - if both are present then bail out
            FileInfo savedFile = null;
            DirectoryInfo savedDir = null;
            //
            foreach ( SXILElement element in aCategory )
            {
                if ( element is SXILElementFile )
                {
                    if ( savedFile != null )
                    {
                        throw new InvalidDataException( "Output file already specified" );
                    }
                    else
                    {
                        SXILElementFile file = (SXILElementFile) element;
                        savedFile = file;
                    }
                }
                else if ( element is SXILElementDirectory )
                {
                    if ( savedDir != null )
                    {
                        throw new InvalidDataException( "Output directory already specified" );
                    }
                    else
                    {
                        SXILElementDirectory dir = (SXILElementDirectory) element;
                        savedDir = dir;
                    }
                }
            }
            
            // Ensure we have only one type
            if ( savedFile != null && savedDir != null )
            {
                throw new InvalidDataException( "Output must be EITHER file or directory" );
            }
            else if ( savedFile != null )
            {
                iSinkParams.OutputFile = savedFile;
            }
            else if ( savedDir != null )
            {
                iSinkParams.OutputDirectory = savedDir;
            }
        }

        public void Trace( string aMessage )
        {
            iEngine.UIManager.UITrace( aMessage );
        }

        public void Trace( string aFormat, params object[] aParams )
        {
            iEngine.UIManager.UITrace( aFormat, aParams );
        }
        #endregion

        #region Data members
        private readonly CAPluginCrashAnalysis iEngine;
        private readonly CISinkSerializationParameters iSinkParams;
        private CACmdLineFSEntityList<CACmdLineFSEntity> iMetaData = new CACmdLineFSEntityList<CACmdLineFSEntity>();
        private CACmdLineFSEntityList<CACmdLineFileSource> iSources = new CACmdLineFSEntityList<CACmdLineFileSource>();
        #endregion
	}
}