|
1 /* |
|
2 * Copyright (c) 2007-2010 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 * Def handler |
|
17 * |
|
18 */ |
|
19 package com.nokia.trace.dictionary.model.handlers; |
|
20 |
|
21 import org.xml.sax.Attributes; |
|
22 |
|
23 import com.nokia.trace.dictionary.TraceDictionaryEngine; |
|
24 import com.nokia.trace.dictionary.model.DecodeObject; |
|
25 import com.nokia.trace.dictionary.model.DictionaryContentHandler; |
|
26 import com.nokia.trace.dictionary.model.DictionaryDecodeModel; |
|
27 import com.nokia.trace.dictionary.model.TraceData; |
|
28 import com.nokia.trace.dictionary.model.decodeparameters.ArrayParameter; |
|
29 import com.nokia.trace.dictionary.model.decodeparameters.ConstantParameter; |
|
30 import com.nokia.trace.dictionary.model.decodeparameters.DecodeParameter; |
|
31 import com.nokia.trace.dictionary.model.decodeparameters.HexParameter; |
|
32 import com.nokia.trace.dictionary.model.decodeparameters.IntegerParameter; |
|
33 import com.nokia.trace.eventrouter.TraceEvent; |
|
34 |
|
35 /** |
|
36 * Def handler |
|
37 */ |
|
38 final class DefHandler extends BaseHandler { |
|
39 |
|
40 /** |
|
41 * Tag name this handler handles |
|
42 */ |
|
43 private static final String DEF_TAG = "def"; //$NON-NLS-1$ |
|
44 |
|
45 /** |
|
46 * Bytes in block |
|
47 */ |
|
48 private int bytesInBlock; |
|
49 |
|
50 /** |
|
51 * Constructor |
|
52 * |
|
53 * @param model |
|
54 * the model |
|
55 */ |
|
56 DefHandler(DictionaryDecodeModel model) { |
|
57 super(model, DEF_TAG); |
|
58 } |
|
59 |
|
60 /* |
|
61 * (non-Javadoc) |
|
62 * |
|
63 * @see com.nokia.trace.dictionary.model.handlers.BaseHandler# |
|
64 * processStartElement(org.xml.sax.Attributes, |
|
65 * com.nokia.trace.dictionary.model.DictionaryContentHandler) |
|
66 */ |
|
67 @Override |
|
68 public void processStartElement(Attributes atts, |
|
69 DictionaryContentHandler handler) { |
|
70 TraceData traceData = new TraceData( |
|
71 Integer.parseInt(atts.getValue(ID)), atts.getValue(TYPE)); |
|
72 handler.catchElementContents(traceData); |
|
73 } |
|
74 |
|
75 /* |
|
76 * (non-Javadoc) |
|
77 * |
|
78 * @see |
|
79 * com.nokia.trace.dictionary.model.handlers.BaseHandler#processEndElement |
|
80 * (java.lang.StringBuffer, java.lang.Object, |
|
81 * com.nokia.trace.dictionary.model.DictionaryContentHandler, |
|
82 * com.nokia.trace.dictionary.model.DecodeObject) |
|
83 */ |
|
84 @Override |
|
85 public void processEndElement(StringBuffer elementContent, |
|
86 Object unFinishedObject, DictionaryContentHandler handler, |
|
87 DecodeObject parentObject) { |
|
88 |
|
89 TraceData traceData = (TraceData) unFinishedObject; |
|
90 |
|
91 // Check if there is only one variable in the trace. If |
|
92 // split has two parts, there is only one variable indicator |
|
93 if (elementContent.toString().split(VARIABLE_INDICATOR).length <= 2) { |
|
94 traceData.setContainsOnlyOneVariable(true); |
|
95 } |
|
96 |
|
97 int startOffset = 0; |
|
98 int foundOffset = 0; |
|
99 int endOffset = 0; |
|
100 |
|
101 // Search all variables from the string |
|
102 while ((foundOffset = elementContent.indexOf(VARIABLE_INDICATOR, |
|
103 startOffset)) != -1) { |
|
104 createConstantParameter(elementContent, traceData, startOffset, |
|
105 foundOffset); |
|
106 |
|
107 String parameterType; |
|
108 StringBuilder digitsSB = new StringBuilder(); |
|
109 boolean isArray = false; |
|
110 |
|
111 int nextCharOffset = foundOffset + 1; |
|
112 |
|
113 // First gather all possible digits to variable. e.g. from %02x |
|
114 // gather 02 |
|
115 char c = elementContent.charAt(nextCharOffset); |
|
116 while (Character.isDigit(c)) { |
|
117 digitsSB.append(c); |
|
118 nextCharOffset++; |
|
119 c = elementContent.charAt(nextCharOffset); |
|
120 } |
|
121 |
|
122 // Check if next char is { |
|
123 if (c == START_BRACKET) { |
|
124 // Find offset of char } |
|
125 endOffset = elementContent.indexOf(Character |
|
126 .toString(END_BRACKET), foundOffset) + 1; |
|
127 |
|
128 // End offset was not found,let's change it to end of whole |
|
129 // string to get some reasonable error message |
|
130 if (endOffset == 0) { |
|
131 endOffset = elementContent.length(); |
|
132 } |
|
133 |
|
134 // Try to find array indicator characters |
|
135 int indexOfBrackets = elementContent.indexOf(ARRAY_INDICATOR, |
|
136 nextCharOffset); |
|
137 // Indicator is found and is inside this parameter -> array |
|
138 if (indexOfBrackets != -1 |
|
139 && indexOfBrackets + ARRAY_INDICATOR.length() < endOffset) { |
|
140 isArray = true; |
|
141 } |
|
142 |
|
143 // Parse from between |
|
144 parameterType = elementContent.substring(nextCharOffset, |
|
145 endOffset); |
|
146 |
|
147 // Next char is not {, so it's a format char |
|
148 } else { |
|
149 |
|
150 // If the first char is L, l, or h, format char has 2 or 3 chars |
|
151 if (c == FORMATCHAR_INDICATOR_BIG_L |
|
152 || c == FORMATCHAR_INDICATOR_SMALL_L |
|
153 || c == FORMATCHAR_INDICATOR_H) { |
|
154 c = elementContent.charAt(nextCharOffset + 1); |
|
155 |
|
156 // Next char is also h or l, format char is 3 chars |
|
157 if (c == FORMATCHAR_INDICATOR_H |
|
158 || c == FORMATCHAR_INDICATOR_SMALL_L) { |
|
159 parameterType = elementContent.substring( |
|
160 nextCharOffset, nextCharOffset |
|
161 + LONG_FORMATCHAR_LENGTH + 1); |
|
162 endOffset = nextCharOffset + LONG_FORMATCHAR_LENGTH + 1; |
|
163 |
|
164 // Format char is 2 chars |
|
165 } else { |
|
166 parameterType = elementContent.substring( |
|
167 nextCharOffset, nextCharOffset |
|
168 + LONG_FORMATCHAR_LENGTH); |
|
169 endOffset = nextCharOffset + LONG_FORMATCHAR_LENGTH; |
|
170 } |
|
171 |
|
172 // Only 1 char |
|
173 } else { |
|
174 parameterType = elementContent.substring(nextCharOffset, |
|
175 nextCharOffset + SHORT_FORMATCHAR_LENGTH); |
|
176 endOffset = nextCharOffset + SHORT_FORMATCHAR_LENGTH; |
|
177 } |
|
178 } |
|
179 |
|
180 DecodeParameter parameter; |
|
181 |
|
182 // Array parameter |
|
183 if (isArray) { |
|
184 parameter = handleArray(traceData, parameterType, digitsSB |
|
185 .toString()); |
|
186 |
|
187 // Normal parameter |
|
188 } else { |
|
189 parameter = getDecodeParameter(parameterType, digitsSB |
|
190 .toString()); |
|
191 |
|
192 if (parameter != null) { |
|
193 // Add possible fillers before this new parameter |
|
194 addFillers(traceData, parameter.getSize()); |
|
195 |
|
196 // Add to the parameter list |
|
197 traceData.addDecodeParameter(parameter); |
|
198 } |
|
199 } |
|
200 |
|
201 // Parameter couldn't be found or created, inform user |
|
202 if (parameter == null) { |
|
203 postParameterNotFoundMsg(handler, parameterType); |
|
204 } |
|
205 |
|
206 // Set start offset to previous end offset |
|
207 startOffset = endOffset; |
|
208 } // while ends |
|
209 |
|
210 // Create constant from the remaining |
|
211 createConstantParameter(elementContent, traceData, startOffset, |
|
212 elementContent.length()); |
|
213 |
|
214 // Add trace data to model |
|
215 model.addTraceData(traceData); |
|
216 |
|
217 // Null bytes in block value afterwards |
|
218 bytesInBlock = 0; |
|
219 } |
|
220 |
|
221 /** |
|
222 * Handles array |
|
223 * |
|
224 * @param traceData |
|
225 * trace data |
|
226 * @param parameterType |
|
227 * parameter type |
|
228 * @param digits |
|
229 * @return created parameter or null if cannot be created |
|
230 */ |
|
231 private DecodeParameter handleArray(TraceData traceData, |
|
232 String parameterType, String digits) { |
|
233 DecodeParameter parameter = null; |
|
234 |
|
235 // Remove array indicator and try decode parameter again |
|
236 String arrayContainsStr = parameterType.replace(ARRAY_INDICATOR, ""); //$NON-NLS-1$ |
|
237 DecodeParameter arrayContains = getDecodeParameter(arrayContainsStr, |
|
238 digits); |
|
239 |
|
240 // Basic type is found, create array parameter and add it |
|
241 // also to the model and to the trace parameter list |
|
242 if (arrayContains != null) { |
|
243 parameter = new ArrayParameter(parameterType, false, arrayContains); |
|
244 |
|
245 model.addDecodeParameter(parameter); |
|
246 traceData.addDecodeParameter(parameter); |
|
247 } |
|
248 |
|
249 return parameter; |
|
250 } |
|
251 |
|
252 /** |
|
253 * Gets (either from model or creates new) decode parameter |
|
254 * |
|
255 * @param parameterType |
|
256 * parameter type to be get |
|
257 * @param digits |
|
258 * possible format digits |
|
259 * @return found or new decode parameter or null if not found |
|
260 */ |
|
261 private DecodeParameter getDecodeParameter(String parameterType, |
|
262 String digits) { |
|
263 String parameterWithFormat = digits + parameterType; |
|
264 |
|
265 // Find from parameter list using the possible formatting (e.g. %02) |
|
266 DecodeParameter parameter = model |
|
267 .getDecodeParameter(parameterWithFormat); |
|
268 |
|
269 // Not found, try to find without the formatting |
|
270 if (parameter == null) { |
|
271 parameter = model.getDecodeParameter(parameterType); |
|
272 |
|
273 // If found, we need to create new decode parameter with the |
|
274 // formatting included |
|
275 if (parameter != null) { |
|
276 parameter = createNewFormatDecodeParameter(parameter, |
|
277 parameterWithFormat, digits); |
|
278 } |
|
279 } |
|
280 |
|
281 return parameter; |
|
282 } |
|
283 |
|
284 /** |
|
285 * Create new decode parameter with formatting |
|
286 * |
|
287 * @param oldParameter |
|
288 * old parameter |
|
289 * @param parameterWithFormat |
|
290 * new parameter name |
|
291 * @param digits |
|
292 * how should the parameter be formatted |
|
293 * @return new decode parameter |
|
294 */ |
|
295 private DecodeParameter createNewFormatDecodeParameter( |
|
296 DecodeParameter oldParameter, String parameterWithFormat, |
|
297 String digits) { |
|
298 DecodeParameter newParameter = null; |
|
299 |
|
300 // This is already checked with "isDigit()" so doesn't need try catch |
|
301 int digit = Integer.parseInt(digits); |
|
302 |
|
303 // Integer parameter |
|
304 if (oldParameter instanceof IntegerParameter) { |
|
305 newParameter = new IntegerParameter(parameterWithFormat, false, |
|
306 oldParameter.getSize(), true); |
|
307 ((IntegerParameter) newParameter).setFormatToChars(digit); |
|
308 } |
|
309 |
|
310 // Hex parameter |
|
311 else if (oldParameter instanceof HexParameter) { |
|
312 newParameter = new HexParameter(parameterWithFormat, false, |
|
313 oldParameter.getSize()); |
|
314 ((HexParameter) newParameter) |
|
315 .setPrintInUpperCase(((HexParameter) oldParameter) |
|
316 .getPrintInUpperCase()); |
|
317 ((HexParameter) newParameter).setFormatToChars(digit); |
|
318 } |
|
319 |
|
320 // Add to the parameter list |
|
321 if (newParameter != null) { |
|
322 model.addDecodeParameter(newParameter); |
|
323 } |
|
324 |
|
325 return newParameter; |
|
326 } |
|
327 |
|
328 /** |
|
329 * Posts parameter not found message to user |
|
330 * |
|
331 * @param handler |
|
332 * Dictionary handler |
|
333 * @param parameterType |
|
334 * parameter type that is not found |
|
335 */ |
|
336 private void postParameterNotFoundMsg(DictionaryContentHandler handler, |
|
337 String parameterType) { |
|
338 String parameterNotFound = Messages |
|
339 .getString("DefHandler.ParameterNotFoundMsg"); //$NON-NLS-1$ |
|
340 TraceEvent event = new TraceEvent(TraceEvent.ERROR, parameterNotFound |
|
341 + parameterType); |
|
342 event.setCategory(EVENT_CATEGORY); |
|
343 event.setSource(Integer.valueOf(handler.getLocator().getLineNumber())); |
|
344 TraceDictionaryEngine.postEvent(event); |
|
345 } |
|
346 |
|
347 /** |
|
348 * Adds possible filler parameters to traceData |
|
349 * |
|
350 * @param traceData |
|
351 * traceData |
|
352 * @param paramSize |
|
353 * size of the new item |
|
354 */ |
|
355 private void addFillers(TraceData traceData, int paramSize) { |
|
356 // Parameters are aligned to 32 bits. Parameter after |
|
357 // end-of-string is aligned dynamically and thus no filler is |
|
358 // created for it |
|
359 if (paramSize == 0 || paramSize == 4 || paramSize == 8) { |
|
360 if (bytesInBlock > 0) { |
|
361 int fillerCount = 4 - bytesInBlock; |
|
362 for (int i = 0; i < fillerCount; i++) { |
|
363 traceData.addDecodeParameter(model.getFillerParameter()); |
|
364 } |
|
365 bytesInBlock = 0; |
|
366 } |
|
367 } else if (paramSize == 2) { |
|
368 if (bytesInBlock == 1 || bytesInBlock == 3) { |
|
369 traceData.addDecodeParameter(model.getFillerParameter()); |
|
370 // If there was 1 existing byte and filler was added, |
|
371 // the number of bytes in the block is now 4 including |
|
372 // the 2-byte parameter. If there was 3 bytes, the |
|
373 // filler brings it to 4 and the 16-bit parameter |
|
374 // changes it to 2 |
|
375 bytesInBlock += 3; |
|
376 } else { |
|
377 bytesInBlock += 2; |
|
378 } |
|
379 if (bytesInBlock >= 4) { |
|
380 bytesInBlock -= 4; |
|
381 } |
|
382 } else { |
|
383 bytesInBlock++; |
|
384 if (bytesInBlock == 4) { |
|
385 bytesInBlock = 0; |
|
386 } |
|
387 } |
|
388 } |
|
389 |
|
390 /** |
|
391 * Create constant parameter |
|
392 * |
|
393 * @param elementContent |
|
394 * buffer where data is |
|
395 * @param traceData |
|
396 * TraceData where to insert this parameter |
|
397 * @param startOffset |
|
398 * start offset from buffer |
|
399 * @param endOffset |
|
400 * end offset from buffer |
|
401 */ |
|
402 private void createConstantParameter(StringBuffer elementContent, |
|
403 TraceData traceData, int startOffset, int endOffset) { |
|
404 |
|
405 // Remove line breaks from the buffer |
|
406 int len = elementContent.length(); |
|
407 for (int i = 0; i < len; i++) { |
|
408 char c = elementContent.charAt(i); |
|
409 if (c == '\n' || c == '\r') { |
|
410 elementContent.setCharAt(i, ' '); |
|
411 } |
|
412 } |
|
413 |
|
414 // First create constant parameter |
|
415 String constantPar = elementContent.substring(startOffset, endOffset); |
|
416 if (constantPar.length() > 0) { |
|
417 // Try to find from the list |
|
418 ConstantParameter parameter = model |
|
419 .getConstantParameter(constantPar); |
|
420 |
|
421 // Couldn't be found |
|
422 if (parameter == null) { |
|
423 parameter = new ConstantParameter(constantPar, false); |
|
424 } |
|
425 |
|
426 // Add to lists |
|
427 traceData.addDecodeParameter(parameter); |
|
428 model.addConstantParameter(parameter); |
|
429 } |
|
430 } |
|
431 |
|
432 } |