|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions are met: |
|
7 * |
|
8 * - Redistributions of source code must retain the above copyright notice, |
|
9 * this list of conditions and the following disclaimer. |
|
10 * - Redistributions in binary form must reproduce the above copyright notice, |
|
11 * this list of conditions and the following disclaimer in the documentation |
|
12 * and/or other materials provided with the distribution. |
|
13 * - Neither the name of Nokia Corporation nor the names of its contributors |
|
14 * may be used to endorse or promote products derived from this software |
|
15 * without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 * POSSIBILITY OF SUCH DAMAGE. |
|
28 * |
|
29 * Initial Contributors: |
|
30 * Nokia Corporation - initial contribution. |
|
31 * |
|
32 * Contributors: |
|
33 * |
|
34 * Description: |
|
35 * |
|
36 */ |
|
37 |
|
38 using System; |
|
39 using System.Text; |
|
40 using System.IO; |
|
41 using System.Collections.Generic; |
|
42 using SymbianUtils.Tracer; |
|
43 using SymbianUtils.FileSystem.Utilities; |
|
44 using SymbianXmlInputLib.Parser; |
|
45 using SymbianXmlInputLib.Parser.Nodes; |
|
46 using SymbianXmlInputLib.Elements; |
|
47 using SymbianXmlInputLib.Elements.Types.Category; |
|
48 using SymbianXmlInputLib.Elements.Types.Extension; |
|
49 using SymbianXmlInputLib.Elements.Types.FileSystem; |
|
50 using SymbianXmlInputLib.Elements.Types.Command; |
|
51 using HeapAnalyser.UIs.Console.Files; |
|
52 using HeapAnalyser.Exceptions; |
|
53 using HeapAnalyser.Engine; |
|
54 |
|
55 namespace HeapAnalyser.UIs.Console.Inputs |
|
56 { |
|
57 internal class HACmdLineInputParameters |
|
58 { |
|
59 #region Constructors & destructor |
|
60 public HACmdLineInputParameters( ITracer aTracer, HeapWizardEngine aEngine ) |
|
61 { |
|
62 iEngine = aEngine; |
|
63 iTracer = aTracer; |
|
64 } |
|
65 #endregion |
|
66 |
|
67 #region API |
|
68 public void Read( string aFileName ) |
|
69 { |
|
70 Trace( "[CmdInput] Read() - aFileName: " + aFileName ); |
|
71 try |
|
72 { |
|
73 // First create the tree |
|
74 SXILDocument doc = CreateDocumentTree( aFileName ); |
|
75 |
|
76 // Then convert it to the list of elements that we care about |
|
77 ExtractData( doc ); |
|
78 } |
|
79 catch ( HAUIException cmdLineException ) |
|
80 { |
|
81 Trace( "[CmdInput] Read() - HAUIException: " + cmdLineException.Message + " " + cmdLineException.StackTrace ); |
|
82 throw cmdLineException; |
|
83 } |
|
84 catch ( Exception generalException ) |
|
85 { |
|
86 Trace( "[CmdInput] Read() - generalException: " + generalException.Message + " " + generalException.StackTrace ); |
|
87 throw new HAUIException( "Error reading input xml file", generalException, HAUIException.KErrCommandLineArgumentsFileInvalid ); |
|
88 } |
|
89 Trace( "[CmdInput] Read() - read OK: " + aFileName ); |
|
90 } |
|
91 #endregion |
|
92 |
|
93 #region Properties |
|
94 public string ThreadName |
|
95 { |
|
96 get { return iThreadName; } |
|
97 } |
|
98 |
|
99 public HACmdLineFSEntity OutputFile |
|
100 { |
|
101 get { return iOutputFile; } |
|
102 } |
|
103 |
|
104 public HACmdLineFSEntityList<HACmdLineFileSource> SourceFiles |
|
105 { |
|
106 get { return iSources; } |
|
107 } |
|
108 |
|
109 public HACmdLineFSEntityList<HACmdLineFSEntity> MetaDataFiles |
|
110 { |
|
111 get { return iMetaData; } |
|
112 } |
|
113 #endregion |
|
114 |
|
115 #region Internal constants |
|
116 private const string KInputFileDocumentRootNode = "heap_analysis"; |
|
117 private const string KInputFileCategorySource = "source"; |
|
118 private const string KInputFileCategoryDebugMetaData = "debug_meta_data"; |
|
119 private const string KInputFileCategoryParameters = "parameters"; |
|
120 private const string KInputFileCategoryOutput = "output"; |
|
121 private const string KInputFileCommandThread = "thread"; |
|
122 private const string KInputFileCommandNameAnalysis = "analysis_type"; |
|
123 private const string KInputFileCommandNameAnalysisViewer = "VIEWER"; |
|
124 private const string KInputFileCommandNameAnalysisCompareTwoHeaps = "COMPARETWOHEAPS"; |
|
125 #endregion |
|
126 |
|
127 #region Internal methods |
|
128 private SXILDocument CreateDocumentTree( string aFileName ) |
|
129 { |
|
130 SXILDocument doc = new SXILDocument(); |
|
131 |
|
132 // Read input file into document |
|
133 using ( SXILParser parser = new SXILParser( aFileName, KInputFileDocumentRootNode, doc ) ) |
|
134 { |
|
135 parser.CategoryAdd( KInputFileCategorySource, new SXILParserNodeFileSystem() ); |
|
136 parser.CategoryAdd( KInputFileCategoryDebugMetaData, new SXILParserNodeFileSystem() ); |
|
137 parser.CategoryAdd( KInputFileCategoryParameters, |
|
138 new SXILParserNodeCommand( KInputFileCommandNameAnalysis ), |
|
139 new SXILParserNodeCommand( KInputFileCommandThread ) |
|
140 ); |
|
141 parser.CategoryAdd( KInputFileCategoryOutput, new SXILParserNodeFileSystem() ); |
|
142 parser.Parse(); |
|
143 } |
|
144 |
|
145 return doc; |
|
146 } |
|
147 |
|
148 private void ExtractData( SXILDocument aDocument ) |
|
149 { |
|
150 foreach ( SXILElement element in aDocument ) |
|
151 { |
|
152 if ( element is SXILElementCategory ) |
|
153 { |
|
154 SXILElementCategory category = (SXILElementCategory) element; |
|
155 string name = category.Name.ToLower(); |
|
156 // |
|
157 switch ( name ) |
|
158 { |
|
159 case KInputFileCategorySource: |
|
160 ExtractFileList<HACmdLineFileSource>( iSources, category, true ); |
|
161 break; |
|
162 case KInputFileCategoryDebugMetaData: |
|
163 ExtractFileList<HACmdLineFSEntity>( iMetaData, category, false ); |
|
164 break; |
|
165 case KInputFileCategoryParameters: |
|
166 ExtractParameters( category ); |
|
167 break; |
|
168 case KInputFileCategoryOutput: |
|
169 ExtractOutput( category ); |
|
170 break; |
|
171 } |
|
172 } |
|
173 } |
|
174 |
|
175 // We don't require debug meta data if performing a summary operation. Otherwise, we do. |
|
176 if ( iMetaData.Count == 0 ) |
|
177 { |
|
178 Trace( "[CmdInput] ExtractData() - no debug meta data supplied!" ); |
|
179 throw new HAUIException( "Debug meta-data not present", HAUIException.KErrCommandLineDebugMetaDataMissing ); |
|
180 } |
|
181 |
|
182 } |
|
183 |
|
184 private void ExtractFileList<T>( HACmdLineFSEntityList<T> aList, SXILElementCategory aCategory, bool aExpandDirectoriesToUnderlyingFiles ) where T : HACmdLineFSEntity, new() |
|
185 { |
|
186 foreach ( SXILElement element in aCategory ) |
|
187 { |
|
188 if ( element is SXILElementFile ) |
|
189 { |
|
190 SXILElementFile file = (SXILElementFile) element; |
|
191 Trace( "[CmdInput] ExtractFileList() - file: " + file ); |
|
192 if ( !file.Exists ) |
|
193 { |
|
194 throw new FileNotFoundException( "File not found", file.Name ); |
|
195 } |
|
196 // |
|
197 aList.Add( file ); |
|
198 } |
|
199 else if ( element is SXILElementDirectory ) |
|
200 { |
|
201 SXILElementDirectory dir = (SXILElementDirectory) element; |
|
202 Trace( "[CmdInput] ExtractFileList() - dir: " + dir ); |
|
203 if ( !dir.Exists ) |
|
204 { |
|
205 throw new DirectoryNotFoundException( "Directory not found: " + dir.Name ); |
|
206 } |
|
207 // |
|
208 if ( aExpandDirectoriesToUnderlyingFiles ) |
|
209 { |
|
210 aList.AddRange( dir.Files ); |
|
211 } |
|
212 else |
|
213 { |
|
214 aList.Add( dir.Directory ); |
|
215 } |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 private void ExtractParameters( SXILElementCategory aCategory ) |
|
221 { |
|
222 foreach ( SXILElement element in aCategory ) |
|
223 { |
|
224 if ( element is SXILElementCommand ) |
|
225 { |
|
226 SXILElementCommand entry = (SXILElementCommand) element; |
|
227 // |
|
228 string type = entry.Details.Trim(); |
|
229 if ( entry.Name == KInputFileCommandNameAnalysis ) |
|
230 { |
|
231 Trace( "[CmdInput] ExtractFileList() - command: " + type ); |
|
232 switch ( type.ToUpper() ) |
|
233 { |
|
234 case KInputFileCommandNameAnalysisViewer: |
|
235 iEngine.OperationType = HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView; |
|
236 break; |
|
237 case KInputFileCommandNameAnalysisCompareTwoHeaps: |
|
238 iEngine.OperationType = HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps; |
|
239 break; |
|
240 default: |
|
241 throw new HAUIException( "Unsupported analysis type", HAUIException.KErrCommandLineAnalysisTypeNotSupported ); |
|
242 } |
|
243 } |
|
244 else if ( entry.Name == KInputFileCommandThread ) |
|
245 { |
|
246 iThreadName = type; |
|
247 } |
|
248 else |
|
249 { |
|
250 throw new HAUIException( "Unsupported command: " + entry.Name, HAUIException.KErrCommandLineInvalidCommand ); |
|
251 } |
|
252 } |
|
253 } |
|
254 } |
|
255 |
|
256 private void ExtractOutput( SXILElementCategory aCategory ) |
|
257 { |
|
258 // We either output to file or directory - if both are present then bail out |
|
259 iOutputFile = null; |
|
260 // |
|
261 foreach ( SXILElement element in aCategory ) |
|
262 { |
|
263 if ( element is SXILElementFile ) |
|
264 { |
|
265 if ( iOutputFile != null ) |
|
266 { |
|
267 throw new HAUIException( "Output specified twice", HAUIException.KErrCommandLineAnalysisOutputInvalid ); |
|
268 } |
|
269 else |
|
270 { |
|
271 SXILElementFile file = (SXILElementFile) element; |
|
272 iOutputFile = new HACmdLineFSEntity(); |
|
273 iOutputFile.File = new FileInfo( file.Name ); |
|
274 } |
|
275 } |
|
276 else if ( element is SXILElementDirectory ) |
|
277 { |
|
278 throw new HAUIException( "Cannot output directory", HAUIException.KErrCommandLineAnalysisOutputInvalid ); |
|
279 } |
|
280 } |
|
281 } |
|
282 |
|
283 public void Trace( string aMessage ) |
|
284 { |
|
285 iTracer.Trace( aMessage ); |
|
286 } |
|
287 |
|
288 public void Trace( string aFormat, params object[] aParams ) |
|
289 { |
|
290 string text = string.Format( aFormat, aParams ); |
|
291 Trace( text ); |
|
292 } |
|
293 #endregion |
|
294 |
|
295 #region Data members |
|
296 private readonly ITracer iTracer; |
|
297 private readonly HeapWizardEngine iEngine; |
|
298 private string iThreadName = string.Empty; |
|
299 private HACmdLineFSEntity iOutputFile = null; |
|
300 private HACmdLineFSEntityList<HACmdLineFSEntity> iMetaData = new HACmdLineFSEntityList<HACmdLineFSEntity>(); |
|
301 private HACmdLineFSEntityList<HACmdLineFileSource> iSources = new HACmdLineFSEntityList<HACmdLineFileSource>(); |
|
302 #endregion |
|
303 } |
|
304 } |