|
1 /* |
|
2 * Copyright (c) 2005-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 |
|
18 |
|
19 |
|
20 |
|
21 #include "stdafx.h" |
|
22 #include "CSTATLogFile.h" |
|
23 #include <statcommon.h> |
|
24 |
|
25 //---------------------------------------------------------------------------- |
|
26 // our thread-safe mechanism - this must be defined, initialised and destroyed by |
|
27 // the code using CSTATEngine. See STATExp.cpp for an example |
|
28 extern CRITICAL_SECTION CriticalSection; |
|
29 //---------------------------------------------------------------------------- |
|
30 |
|
31 //---------------------------------------------------------------------------- |
|
32 //standard constructor |
|
33 CSTATLogFile::CSTATLogFile() |
|
34 : bMessageBox(false), bMessage(false), bWriteToScreen(false), bWriteToFile(false), bScreenshot(false), |
|
35 iMessageReporter(NULL) |
|
36 { |
|
37 message = _T(""); |
|
38 text = _T(""); |
|
39 *(szLogPrefix) = (char)0; |
|
40 } |
|
41 |
|
42 //---------------------------------------------------------------------------- |
|
43 //destructor |
|
44 CSTATLogFile::~CSTATLogFile() |
|
45 { |
|
46 CloseLogFile(); |
|
47 } |
|
48 |
|
49 |
|
50 //---------------------------------------------------------------------------- |
|
51 // opens (creates) logfile |
|
52 int CSTATLogFile::CreateLogFile(const CString& newlogfilename,const CString& defaultPath, const char* prefix, bool append, bool bMessages, bool bFile) |
|
53 { |
|
54 // set flags to write to dialog screen/file |
|
55 bWriteToScreen = bMessages; |
|
56 bWriteToFile = bFile; |
|
57 |
|
58 // construct our log file |
|
59 if (bWriteToFile) |
|
60 { |
|
61 EnterCriticalSection(&CriticalSection); |
|
62 |
|
63 // in case it's already open |
|
64 CloseLogFile(); |
|
65 |
|
66 int position; |
|
67 UINT openFlags = CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone; |
|
68 |
|
69 // if newlogfilename contains a path, use it otherwise get the default log directory |
|
70 position = newlogfilename.ReverseFind('\\'); |
|
71 if (position != -1) |
|
72 { |
|
73 Logfilename = newlogfilename; |
|
74 CreateDirectory(Logfilename.Left(position), NULL); // try to create directory just in case |
|
75 } |
|
76 else |
|
77 { |
|
78 Logfilename=defaultPath; |
|
79 if (Logfilename[Logfilename.GetLength() - 1] != _T('\\')) |
|
80 Logfilename += _T("\\"); |
|
81 |
|
82 Logfilename += newlogfilename; |
|
83 CreateDirectory(Logfilename, NULL); // try to create directory just in case |
|
84 } |
|
85 |
|
86 // just path supplied, add a filename |
|
87 if (Logfilename[Logfilename.GetLength() - 1] == _T('\\')) |
|
88 { |
|
89 char FormattedDate[12] = {0}; |
|
90 Logfilename += _T("STAT"); |
|
91 Logfilename += _strdate(FormattedDate); // ...\\filename is now 'STATmm/dd/yy' |
|
92 Logfilename.Remove('/'); // ...\\filename is now 'STATmmddyy' |
|
93 } |
|
94 |
|
95 // add extension if not supplied |
|
96 if(Logfilename.ReverseFind('.') == -1) |
|
97 Logfilename += _T(".log"); |
|
98 |
|
99 // if not append, create a new file every time, renaming with (1),(2)...(n) as needed |
|
100 CFileFind finder; |
|
101 if (!append) |
|
102 { |
|
103 CString tempLogfile, tempLogstart, tempLogend; |
|
104 char szCopycount[15] = {0}; |
|
105 int iCopycount = 1; |
|
106 |
|
107 // save various bits |
|
108 tempLogfile = Logfilename; |
|
109 position = tempLogfile.ReverseFind('.'); |
|
110 tempLogstart = tempLogfile.Left(position); |
|
111 tempLogend = Logfilename.Right(Logfilename.GetLength() - position); |
|
112 |
|
113 while (finder.FindFile(tempLogfile, 0)) |
|
114 { |
|
115 if (position > 0) |
|
116 { |
|
117 tempLogfile = tempLogstart; |
|
118 tempLogfile += "("; |
|
119 tempLogfile += itoa(iCopycount++, szCopycount, 10); |
|
120 tempLogfile += ")"; |
|
121 tempLogfile += tempLogend; |
|
122 } |
|
123 finder.Close(); |
|
124 } |
|
125 |
|
126 // assign new filename |
|
127 Logfilename = tempLogfile; |
|
128 } |
|
129 else |
|
130 { |
|
131 // if it already exists, open simple in case other handles are open on it |
|
132 if (finder.FindFile(Logfilename, 0)) |
|
133 { |
|
134 openFlags = CFile::modeWrite | CFile::shareDenyNone; |
|
135 finder.Close(); |
|
136 } |
|
137 } |
|
138 |
|
139 // open the file |
|
140 int valid = logfile.Open(Logfilename, openFlags); |
|
141 if (valid) |
|
142 { |
|
143 logfile.SeekToEnd(); |
|
144 if (prefix && *prefix) |
|
145 { |
|
146 strcpy(szLogPrefix, " "); |
|
147 strcat(szLogPrefix, prefix); |
|
148 } |
|
149 } |
|
150 |
|
151 LeaveCriticalSection(&CriticalSection); |
|
152 |
|
153 if (!valid) |
|
154 return LOG_FILE_FAILURE; |
|
155 } |
|
156 |
|
157 return LOG_FILE_OK; |
|
158 } |
|
159 |
|
160 //---------------------------------------------------------------------------- |
|
161 // Specifies the message handler. |
|
162 void CSTATLogFile::SetMessageReporter(MessageReporter *const messageReporter) |
|
163 { |
|
164 iMessageReporter = messageReporter; |
|
165 } |
|
166 |
|
167 //---------------------------------------------------------------------------- |
|
168 // sets a log message |
|
169 void |
|
170 CSTATLogFile::WriteTimeToLog() |
|
171 { |
|
172 if (logfile.m_hFile != CFile::hFileNull) |
|
173 { |
|
174 EnterCriticalSection(&CriticalSection); |
|
175 |
|
176 // get the time |
|
177 time_t aclock; |
|
178 time(&aclock); |
|
179 CString cBuf = asctime(localtime(&aclock)); |
|
180 int position = cBuf.Find(_T('\n')); // remove the carriage return from the end |
|
181 if (position != -1) |
|
182 cBuf.SetAt(position, 0); |
|
183 |
|
184 Write("--------------------------------------------------\r\n"); |
|
185 Write(FormatText(cBuf)); |
|
186 |
|
187 logfile.Flush(); |
|
188 |
|
189 LeaveCriticalSection(&CriticalSection); |
|
190 } |
|
191 } |
|
192 |
|
193 |
|
194 //---------------------------------------------------------------------------- |
|
195 // writes CString directly to the log file |
|
196 void |
|
197 CSTATLogFile::Write(CString cBuf) |
|
198 { |
|
199 Write(FormatText(cBuf)); |
|
200 } |
|
201 |
|
202 |
|
203 //---------------------------------------------------------------------------- |
|
204 //writes basic text directly to the log file |
|
205 void CSTATLogFile::Write(char *szText, ...) |
|
206 { |
|
207 if (logfile.m_hFile != CFile::hFileNull) |
|
208 { |
|
209 EnterCriticalSection(&CriticalSection); |
|
210 |
|
211 static char szMessage[MAX_LOG_MSG_LEN + 1]; |
|
212 static time_t curTime; |
|
213 |
|
214 logfile.SeekToEnd(); |
|
215 logfile.Write(szLogPrefix, strlen(szLogPrefix)); |
|
216 |
|
217 // write the date/time |
|
218 time ( &curTime ); |
|
219 strftime ( szMessage, |
|
220 sizeof ( szMessage ), |
|
221 "%d/%m %H:%M:%S ", |
|
222 localtime ( &curTime ) ); |
|
223 logfile.Write(szMessage, strlen(szMessage)); |
|
224 |
|
225 // write the message |
|
226 memset(&szMessage, 0, sizeof(szMessage)); |
|
227 va_list pCurrent = (va_list)0; |
|
228 va_start (pCurrent, szText); |
|
229 vsprintf (szMessage, szText, pCurrent); |
|
230 va_end (pCurrent); |
|
231 logfile.Write(szMessage, strlen(szMessage)); |
|
232 |
|
233 // add a CRLF if there isn't one already |
|
234 if (strlen(szMessage) > 2) |
|
235 if (strcmp(szMessage + strlen(szMessage) - 2, "\r\n") != 0) |
|
236 logfile.Write("\r\n", 2); |
|
237 |
|
238 logfile.Flush(); |
|
239 |
|
240 LeaveCriticalSection(&CriticalSection); |
|
241 } |
|
242 } |
|
243 |
|
244 |
|
245 //---------------------------------------------------------------------------- |
|
246 // sets a log message (same as Write() but subject to waiting for previous |
|
247 // message to be processed before returning (if multi-threaded write to screen |
|
248 // is enabled) |
|
249 int |
|
250 CSTATLogFile::Set(const char* newtext) |
|
251 { |
|
252 Set(-1, newtext, false, false); |
|
253 return ITS_OK; |
|
254 } |
|
255 |
|
256 //---------------------------------------------------------------------------- |
|
257 // sets a log message (same as Write() but subject to waiting for previous |
|
258 // message to be processed before returning (if multi-threaded write to screen |
|
259 // is enabled) |
|
260 int |
|
261 CSTATLogFile::Set(int iMsgCode, const char* newtext, bool bMsgBox, bool bScrshot) |
|
262 { |
|
263 // write to screen |
|
264 if (bWriteToScreen && (NULL != iMessageReporter)) |
|
265 { |
|
266 // set contents |
|
267 if (iMsgCode != -1) |
|
268 { |
|
269 message = ReturnCodes.GetRetMsg(iMsgCode); |
|
270 } |
|
271 else |
|
272 { |
|
273 message.Empty( ); |
|
274 } |
|
275 |
|
276 if ((newtext != NULL) && (*newtext != '\0')) |
|
277 { |
|
278 text = newtext; |
|
279 } |
|
280 |
|
281 iMessageReporter->OnMessage( message.operator LPCTSTR(), text.operator LPCTSTR(), |
|
282 bMsgBox, bScrshot ); |
|
283 } |
|
284 |
|
285 // write to file |
|
286 if (bWriteToFile) |
|
287 { |
|
288 EnterCriticalSection(&CriticalSection); |
|
289 |
|
290 if (iMsgCode != -1) |
|
291 Write(FormatText(ReturnCodes.GetRetMsg(iMsgCode))); |
|
292 |
|
293 if ((newtext != NULL) && (*newtext != '\0')) |
|
294 Write(FormatText(newtext)); |
|
295 |
|
296 LeaveCriticalSection(&CriticalSection); |
|
297 } |
|
298 |
|
299 return iMsgCode; |
|
300 } |
|
301 |
|
302 //---------------------------------------------------------------------------- |
|
303 //closes the active logfile |
|
304 void CSTATLogFile::CloseLogFile() |
|
305 { |
|
306 EnterCriticalSection(&CriticalSection); |
|
307 |
|
308 if (logfile.m_hFile != CFile::hFileNull) |
|
309 logfile.Abort(); |
|
310 |
|
311 LeaveCriticalSection(&CriticalSection); |
|
312 } |
|
313 |
|
314 |
|
315 //---------------------------------------------------------------------------- |
|
316 // PRIVATE METHODS |
|
317 //---------------------------------------------------------------------------- |
|
318 |
|
319 //---------------------------------------------------------------------------- |
|
320 //removes spacing between data when writing to file |
|
321 char* CSTATLogFile::FormatText(const char* message) |
|
322 { |
|
323 int newlen = 0; |
|
324 static char szBuffer[MAX_LOG_MSG_LEN + 3]; |
|
325 int maxlen = strlen(message); |
|
326 |
|
327 if (maxlen > MAX_LOG_MSG_LEN) |
|
328 maxlen = MAX_LOG_MSG_LEN; |
|
329 |
|
330 (*szBuffer) = (char)0; |
|
331 newlen = ToAnsi(message, szBuffer, maxlen); |
|
332 |
|
333 // add CR-LF and null-terminate, even if an empty string |
|
334 *(szBuffer + newlen) = (char)0; |
|
335 strcat(szBuffer, "\r\n"); |
|
336 |
|
337 return szBuffer; |
|
338 } |
|
339 |
|
340 |
|
341 //---------------------------------------------------------------------------- |
|
342 //function to convert unicode to ansi - for logging |
|
343 int CSTATLogFile::ToAnsi(LPCTSTR szUnicode, LPSTR szBuffer, int nBufLen) |
|
344 { |
|
345 #ifdef UNICODE |
|
346 return (WideCharToMultiByte(CP_ACP, // conversion type |
|
347 0, // flags |
|
348 szUnicode, // source |
|
349 nBufLen, // length |
|
350 szBuffer, // dest |
|
351 nBufLen, // length |
|
352 NULL, |
|
353 NULL)); |
|
354 #else |
|
355 strncpy(szBuffer, szUnicode, nBufLen); |
|
356 *(szBuffer + nBufLen) = (char)0; |
|
357 return strlen(szBuffer); |
|
358 #endif |
|
359 } |
|
360 |
|
361 |
|
362 ////////////////////////////////////////////////////////////////////////////////////////// |
|
363 // Converts a char * to it's Unicode equivalent |
|
364 // |
|
365 LPCTSTR |
|
366 CSTATLogFile::ToUnicode(const char *string) |
|
367 { |
|
368 #ifdef UNICODE |
|
369 static TCHAR szBuffer[MAX_LOG_MSG_LEN + 1] = {0}; |
|
370 szBuffer[0] = (TCHAR)0; |
|
371 |
|
372 // Convert to UNICODE. |
|
373 if (!MultiByteToWideChar(CP_ACP, // conversion type |
|
374 0, // flags |
|
375 string, // source |
|
376 -1, // length |
|
377 szBuffer, // dest |
|
378 MAX_LOG_MSG_LEN)) // length |
|
379 { |
|
380 return _T("Unable to convert ansi to unicode"); |
|
381 } |
|
382 |
|
383 return szBuffer; |
|
384 #else |
|
385 return string; |
|
386 #endif |
|
387 } |