rUtilAnts 0.1.0.20091014

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,445 @@
1
+ #--
2
+ # Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ # This file declares modules that might be shared across several projects.
7
+
8
+ module RUtilAnts
9
+
10
+ module Logging
11
+
12
+ # The logger class singleton
13
+ class Logger
14
+
15
+ # Constants used for GUI dialogs selection
16
+ GUI_WX = 0
17
+
18
+ # Constructor
19
+ #
20
+ # Parameters:
21
+ # * *iLibRootDir* (_String_): The library root directory that will not appear in the logged stack messages
22
+ # * *iBugTrackerURL* (_String_): The application's bug tracker URL, used to report bugs
23
+ # * *iSilentOutputs* (_Boolean_): Do we silent outputs (nothing sent to $stdout or $stderr) ? [optional = false]
24
+ def initialize(iLibRootDir, iBugTrackerURL, iSilentOutputs = false)
25
+ @LibRootDir, @BugTrackerURL = iLibRootDir, iBugTrackerURL
26
+ @DebugMode = false
27
+ @LogFile = nil
28
+ @ErrorsStack = nil
29
+ @MessagesStack = nil
30
+ @DialogsGUI = nil
31
+ @ScreenOutput = (!iSilentOutputs)
32
+ @ScreenOutputErr = (!iSilentOutputs)
33
+ if (!iSilentOutputs)
34
+ # Test if we can write to stdout
35
+ begin
36
+ $stdout << "Launch Logging - stdout\n"
37
+ rescue Exception
38
+ # Redirect to a file if possible
39
+ begin
40
+ lFile = File.open('./stdout', 'w')
41
+ $stdout.reopen(lFile)
42
+ $stdout << "Launch Logging - stdout\n"
43
+ rescue Exception
44
+ # Disable
45
+ @ScreenOutput = false
46
+ end
47
+ end
48
+ # Test if we can write to stderr
49
+ begin
50
+ $stderr << "Launch Logging - stderr\n"
51
+ rescue Exception
52
+ # Redirect to a file if possible
53
+ begin
54
+ lFile = File.open('./stderr', 'w')
55
+ $stderr.reopen(lFile)
56
+ $stderr << "Launch Logging - stderr\n"
57
+ rescue Exception
58
+ # Disable
59
+ @ScreenOutputErr = false
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # Set the log file to use (can be nil to stop logging into a file)
66
+ #
67
+ # Parameters:
68
+ # * *iFileName* (_String_): Log file name (can be nil)
69
+ def setLogFile(iFileName)
70
+ @LogFile = iFileName
71
+ end
72
+
73
+ # Indicate which GUI to be used to display dialogs.
74
+ #
75
+ # Parameters:
76
+ # * *iGUIToUse* (_Integer_): The GUI constant, or nil if no GUI is provided
77
+ def setGUIForDialogs(iGUIToUse)
78
+ @DialogsGUI = iGUIToUse
79
+ end
80
+
81
+ # Set the debug mode
82
+ #
83
+ # Parameters:
84
+ # * *iDebugMode* (_Boolean_): Are we in debug mode ?
85
+ def activateLogDebug(iDebugMode)
86
+ @DebugMode = iDebugMode
87
+ if (iDebugMode)
88
+ logInfo 'Activated log debug'
89
+ else
90
+ logInfo 'Deactivated log debug'
91
+ end
92
+ end
93
+
94
+ # Set the stack of the errors to fill.
95
+ # If set to nil, errors will be displayed as they appear.
96
+ # If set to a stack, errors will silently be added to the list.
97
+ #
98
+ # Parameters:
99
+ # * *iErrorsStack* (<em>list<String></em>): The stack of errors, or nil to unset it
100
+ def setLogErrorsStack(iErrorsStack)
101
+ @ErrorsStack = iErrorsStack
102
+ end
103
+
104
+ # Set the stack of the messages to fill.
105
+ # If set to nil, messages will be displayed as they appear.
106
+ # If set to a stack, messages will silently be added to the list.
107
+ #
108
+ # Parameters:
109
+ # * *iMessagesStack* (<em>list<String></em>): The stack of messages, or nil to unset it
110
+ def setLogMessagesStack(iMessagesStack)
111
+ @MessagesStack = iMessagesStack
112
+ end
113
+
114
+ # Log an exception
115
+ # This is called when there is a bug due to an exception in the program. It has been set in many places to detect bugs.
116
+ #
117
+ # Parameters:
118
+ # * *iException* (_Exception_): Exception
119
+ # * *iMsg* (_String_): Message to log
120
+ def logExc(iException, iMsg)
121
+ logBug("#{iMsg}
122
+ Exception: #{iException}
123
+ Exception stack:
124
+ #{getSimpleCaller(iException.backtrace, caller).join("\n")}
125
+ ...")
126
+ end
127
+
128
+ # Log a bug
129
+ # This is called when there is a bug in the program. It has been set in many places to detect bugs.
130
+ #
131
+ # Parameters:
132
+ # * *iMsg* (_String_): Message to log
133
+ def logBug(iMsg)
134
+ lCompleteMsg = "Bug: #{iMsg}
135
+ Stack:
136
+ #{getSimpleCaller(caller[0..-2]).join("\n")}"
137
+ # Log into stderr
138
+ if (@ScreenOutputErr)
139
+ $stderr << "!!! BUG !!! #{lCompleteMsg}\n"
140
+ end
141
+ if (@LogFile != nil)
142
+ logFile(lCompleteMsg)
143
+ end
144
+ # Display Bug dialog
145
+ if (showModalWxAvailable?)
146
+ # We require the file here, as we hope it will not be required often
147
+ require 'RUtilAnts/GUI/BugReportDialog'
148
+ showModal(GUI::BugReportDialog, nil, lCompleteMsg, @BugTrackerURL) do |iModalResult, iDialog|
149
+ # Nothing to do
150
+ end
151
+ else
152
+ # Use normal platform dependent message, if the platform has been initialized (otherwise, stick to $stderr)
153
+ if (defined?($rUtilAnts_Platform_Info) != nil)
154
+ $rUtilAnts_Platform_Info.sendMsg("A bug has just occurred.
155
+ Normally you should never see this message, but this application is not bug-less.
156
+ We are sorry for the inconvenience caused.
157
+ If you want to help improving this application, please inform us of this bug:
158
+ take the time to open a ticket at the bugs tracker.
159
+ We will always try our best to correct bugs.
160
+ Thanks.
161
+
162
+ Details:
163
+ #{lCompleteMsg}
164
+ ")
165
+ end
166
+ end
167
+ end
168
+
169
+ # Log an error.
170
+ # Those errors can be normal, as they mainly depend on external factors (lost connection, invalid user file...)
171
+ #
172
+ # Parameters:
173
+ # * *iMsg* (_String_): Message to log
174
+ def logErr(iMsg)
175
+ # Log into stderr
176
+ if (@ScreenOutputErr)
177
+ $stderr << "!!! ERR !!! #{iMsg}\n"
178
+ end
179
+ if (@LogFile != nil)
180
+ logFile(iMsg)
181
+ end
182
+ # Display dialog only if we are not redirecting messages to a stack
183
+ if (@ErrorsStack == nil)
184
+ if (showModalWxAvailable?)
185
+ showModal(Wx::MessageDialog, nil,
186
+ iMsg,
187
+ :caption => 'Error',
188
+ :style => Wx::OK|Wx::ICON_ERROR
189
+ ) do |iModalResult, iDialog|
190
+ # Nothing to do
191
+ end
192
+ elsif (defined?($rUtilAnts_Platform_Info) != nil)
193
+ # Use normal platform dependent message, if the platform has been initialized (otherwise, stick to $stderr)
194
+ $rUtilAnts_Platform_Info.sendMsg(iMsg)
195
+ end
196
+ else
197
+ @ErrorsStack << iMsg
198
+ end
199
+ end
200
+
201
+ # Log a normal message to the user
202
+ # This is used to display a simple message to the user
203
+ #
204
+ # Parameters:
205
+ # * *iMsg* (_String_): Message to log
206
+ def logMsg(iMsg)
207
+ # Log into stderr
208
+ if (@ScreenOutput)
209
+ $stdout << "#{iMsg}\n"
210
+ end
211
+ if (@LogFile != nil)
212
+ logFile(iMsg)
213
+ end
214
+ # Display dialog only if we are not redirecting messages to a stack
215
+ if (@MessagesStack == nil)
216
+ # Display dialog only if showModal exists and that we are currently running the application
217
+ if (showModalWxAvailable?)
218
+ showModal(Wx::MessageDialog, nil,
219
+ iMsg,
220
+ :caption => 'Notification',
221
+ :style => Wx::OK|Wx::ICON_INFORMATION
222
+ ) do |iModalResult, iDialog|
223
+ # Nothing to do
224
+ end
225
+ elsif (defined?($rUtilAnts_Platform_Info) != nil)
226
+ # Use normal platform dependent message, if the platform has been initialized (otherwise, stick to $stderr)
227
+ $rUtilAnts_Platform_Info.sendMsg(iMsg)
228
+ end
229
+ else
230
+ @MessagesStack << iMsg
231
+ end
232
+ end
233
+
234
+ # Log an info.
235
+ # This is just common journal.
236
+ #
237
+ # Parameters:
238
+ # * *iMsg* (_String_): Message to log
239
+ def logInfo(iMsg)
240
+ # Log into stdout
241
+ if (@ScreenOutput)
242
+ $stdout << "#{iMsg}\n"
243
+ end
244
+ if (@LogFile != nil)
245
+ logFile(iMsg)
246
+ end
247
+ end
248
+
249
+ # Log a debugging info.
250
+ # This is used when debug is activated
251
+ #
252
+ # Parameters:
253
+ # * *iMsg* (_String_): Message to log
254
+ def logDebug(iMsg)
255
+ # Log into stdout
256
+ if ((@DebugMode) and
257
+ (@ScreenOutput))
258
+ $stdout << "#{iMsg}\n"
259
+ end
260
+ if (@LogFile != nil)
261
+ logFile(iMsg)
262
+ end
263
+ end
264
+
265
+ private
266
+
267
+ # Check if Wx dialogs environment is set up
268
+ #
269
+ # Return:
270
+ # * _Boolean_: Can we use showModal ?
271
+ def showModalWxAvailable?
272
+ return (
273
+ (defined?(showModal) != nil) and
274
+ (@DialogsGUI == GUI_WX)
275
+ )
276
+ end
277
+
278
+ # Log a message in the log file
279
+ #
280
+ # Parameters:
281
+ # * *iMsg* (_String_): The message to log
282
+ def logFile(iMsg)
283
+ File.open(@LogFile, 'a+') do |oFile|
284
+ oFile << "#{Time.now.gmtime.strftime('%Y/%m/%d %H:%M:%S')} - #{iMsg}\n"
285
+ end
286
+ end
287
+
288
+ # Get a stack trace in a simple format:
289
+ # Remove @LibRootDir paths from it.
290
+ #
291
+ # Parameters:
292
+ # * *iCaller* (<em>list<String></em>): The caller
293
+ # * *iReferenceCaller* (<em>list<String></em>): The reference caller: we will not display lines from iCaller that also belong to iReferenceCaller [optional = nil]
294
+ # Return:
295
+ # * <em>list<String></em>): The simple stack
296
+ def getSimpleCaller(iCaller, iReferenceCaller = nil)
297
+ rSimpleCaller = []
298
+
299
+ lCaller = nil
300
+ # If there is a reference caller, remove the lines from lCaller that are also in iReferenceCaller
301
+ if (iReferenceCaller == nil)
302
+ lCaller = iCaller
303
+ else
304
+ lIdxCaller = iCaller.size - 1
305
+ lIdxRef = iReferenceCaller.size - 1
306
+ while ((lIdxCaller >= 0) and
307
+ (lIdxRef >= 0) and
308
+ (iCaller[lIdxCaller] == iReferenceCaller[lIdxRef]))
309
+ lIdxCaller -= 1
310
+ lIdxRef -= 1
311
+ end
312
+ # Here we have either one of the indexes that is -1, or the indexes point to different lines between the caller and its reference.
313
+ lCaller = iCaller[0..lIdxCaller+1]
314
+ end
315
+ lCaller.each do |iCallerLine|
316
+ lMatch = iCallerLine.match(/^(.*):([[:digit:]]*):in (.*)$/)
317
+ if (lMatch == nil)
318
+ # Did not get which format. Just add it blindly.
319
+ rSimpleCaller << iCallerLine
320
+ else
321
+ rSimpleCaller << "#{File.expand_path(lMatch[1]).gsub(@LibRootDir, '')}:#{lMatch[2]}:in #{lMatch[3]}"
322
+ end
323
+ end
324
+
325
+ return rSimpleCaller
326
+ end
327
+
328
+ end
329
+
330
+ # The following methods are meant to be included in a class to be easily useable.
331
+
332
+ # Initialize the logging features
333
+ #
334
+ # Parameters:
335
+ # * *iLibRootDir* (_String_): The library root directory that will not appear in the logged stack messages
336
+ # * *iBugTrackerURL* (_String_): The application's bug tracker URL, used to report bugs
337
+ # * *iSilentOutputs* (_Boolean_): Do we silent outputs (nothing sent to $stdout or $stderr) ? [optional = false]
338
+ def self.initializeLogging(iLibRootDir, iBugTrackerURL, iSilentOutputs = false)
339
+ $rUtilAnts_Logging_Logger = RUtilAnts::Logging::Logger.new(iLibRootDir, iBugTrackerURL, iSilentOutputs)
340
+ # Add the module accessible from the Kernel
341
+ Object.module_eval('include RUtilAnts::Logging')
342
+ end
343
+
344
+ # Set the log file to use (can be nil to stop logging into a file)
345
+ #
346
+ # Parameters:
347
+ # * *iFileName* (_String_): Log file name (can be nil)
348
+ def setLogFile(iFileName)
349
+ $rUtilAnts_Logging_Logger.setLogFile(iFileName)
350
+ end
351
+
352
+ # Indicate which GUI to be used to display dialogs.
353
+ #
354
+ # Parameters:
355
+ # * *iGUIToUse* (_Integer_): The GUI constant, or nil if no GUI is provided
356
+ def setGUIForDialogs(iGUIToUse)
357
+ $rUtilAnts_Logging_Logger.setGUIForDialogs(iGUIToUse)
358
+ end
359
+
360
+ # Set the debug mode
361
+ #
362
+ # Parameters:
363
+ # * *iDebugMode* (_Boolean_): Are we in debug mode ?
364
+ def activateLogDebug(iDebugMode)
365
+ $rUtilAnts_Logging_Logger.activateLogDebug(iDebugMode)
366
+ end
367
+
368
+ # Set the stack of the errors to fill.
369
+ # If set to nil, errors will be displayed as they appear.
370
+ # If set to a stack, errors will silently be added to the list.
371
+ #
372
+ # Parameters:
373
+ # * *iErrorsStack* (<em>list<String></em>): The stack of errors, or nil to unset it
374
+ def setLogErrorsStack(iErrorsStack)
375
+ $rUtilAnts_Logging_Logger.setLogErrorsStack(iErrorsStack)
376
+ end
377
+
378
+ # Set the stack of the messages to fill.
379
+ # If set to nil, messages will be displayed as they appear.
380
+ # If set to a stack, messages will silently be added to the list.
381
+ #
382
+ # Parameters:
383
+ # * *iMessagesStack* (<em>list<String></em>): The stack of messages, or nil to unset it
384
+ def setLogMessagesStack(iMessagesStack)
385
+ $rUtilAnts_Logging_Logger.setLogMessagesStack(iMessagesStack)
386
+ end
387
+
388
+ # Log an exception
389
+ # This is called when there is a bug due to an exception in the program. It has been set in many places to detect bugs.
390
+ #
391
+ # Parameters:
392
+ # * *iException* (_Exception_): Exception
393
+ # * *iMsg* (_String_): Message to log
394
+ def logExc(iException, iMsg)
395
+ $rUtilAnts_Logging_Logger.logExc(iException, iMsg)
396
+ end
397
+
398
+ # Log a bug
399
+ # This is called when there is a bug in the program. It has been set in many places to detect bugs.
400
+ #
401
+ # Parameters:
402
+ # * *iMsg* (_String_): Message to log
403
+ def logBug(iMsg)
404
+ $rUtilAnts_Logging_Logger.logBug(iMsg)
405
+ end
406
+
407
+ # Log an error.
408
+ # Those errors can be normal, as they mainly depend on external factors (lost connection, invalid user file...)
409
+ #
410
+ # Parameters:
411
+ # * *iMsg* (_String_): Message to log
412
+ def logErr(iMsg)
413
+ $rUtilAnts_Logging_Logger.logErr(iMsg)
414
+ end
415
+
416
+ # Log a normal message to the user
417
+ # This is used to display a simple message to the user
418
+ #
419
+ # Parameters:
420
+ # * *iMsg* (_String_): Message to log
421
+ def logMsg(iMsg)
422
+ $rUtilAnts_Logging_Logger.logMsg(iMsg)
423
+ end
424
+
425
+ # Log an info.
426
+ # This is just common journal.
427
+ #
428
+ # Parameters:
429
+ # * *iMsg* (_String_): Message to log
430
+ def logInfo(iMsg)
431
+ $rUtilAnts_Logging_Logger.logInfo(iMsg)
432
+ end
433
+
434
+ # Log a debugging info.
435
+ # This is used when debug is activated
436
+ #
437
+ # Parameters:
438
+ # * *iMsg* (_String_): Message to log
439
+ def logDebug(iMsg)
440
+ $rUtilAnts_Logging_Logger.logDebug(iMsg)
441
+ end
442
+
443
+ end
444
+
445
+ end
@@ -0,0 +1,132 @@
1
+ #--
2
+ # Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ module RUtilAnts
7
+
8
+ module Misc
9
+
10
+ # Set these methods into the Kernel namespace
11
+ def self.initializeMisc
12
+ Object.module_eval('include RUtilAnts::Misc')
13
+ end
14
+
15
+ # Get a valid file name, taking into account platform specifically prohibited characters in file names.
16
+ #
17
+ # Parameters:
18
+ # * *iFileName* (_String_): The original file name wanted
19
+ # Return:
20
+ # * _String_: The correct file name
21
+ def getValidFileName(iFileName)
22
+ if ((defined?($rUtilAnts_Platform_Info) != nil))
23
+ return iFileName.gsub(/[#{Regexp.escape($rUtilAnts_Platform_Info.getProhibitedFileNamesCharacters)}]/, '_')
24
+ else
25
+ return iFileName
26
+ end
27
+ end
28
+
29
+ # Extract a Zip archive in a given system dependent lib sub-directory
30
+ #
31
+ # Parameters:
32
+ # * *iZipFileName* (_String_): The zip file name to extract content from
33
+ # * *iDirName* (_String_): The name of the directory to store the zip to
34
+ # Return:
35
+ # * _Exception_: Error, or nil in case of success
36
+ def extractZipFile(iZipFileName, iDirName)
37
+ rError = nil
38
+
39
+ # Use RDI if possible to ensure the dependencies on zlib.dll and rubyzip
40
+ if (defined?(RDI) != nil)
41
+ lRDIInstaller = RDI::Installer.getMainInstance
42
+ if (lRDIInstaller != nil)
43
+ # First, test that the DLL exists.
44
+ # If it does not exist, we can't install it, because ZLib.dll is downloadable only in ZIP format (kind of stupid ;-) )
45
+ lDLLDep = nil
46
+ case $rUtilAnts_Platform_Info.os
47
+ when OS_WINDOWS
48
+ lDLLDep = RDI::Model::DependencyDescription.new('ZLib DLL').addDescription( {
49
+ :Testers => [
50
+ {
51
+ :Type => 'DynamicLibraries',
52
+ :Content => [ 'zlib.dll' ]
53
+ }
54
+ ],
55
+ # We can't install this one
56
+ :Installers => []
57
+ } )
58
+ else
59
+ logBug "Sorry, installing ZLib on your platform #{$rUtilAnts_Platform_Info.os} is not yet supported."
60
+ end
61
+ if ((lDLLDep != nil) and
62
+ (!lRDIInstaller.testDependency(lDLLDep)))
63
+ # Try adding the default local location for libraries
64
+ lRDIInstaller.ensureLocationInContext('LibraryPath', lRDIInstaller.getDefaultInstallLocation('Download', RDI::DEST_LOCAL))
65
+ # Try again
66
+ if (!lRDIInstaller.testDependency(lDLLDep))
67
+ logErr "zlib.dll is not installed in your system.\nUnfortunately RDI can't help because the only way to install it is to download it through a ZIP file.\nPlease install it manually from http://zlib.net (you can do it now and click OK once it is installed)."
68
+ end
69
+ end
70
+ # Then, ensure the gem dependency
71
+ rError, lCMApplied, lIgnored, lUnresolved = lRDIInstaller.ensureDependencies(
72
+ [
73
+ RDI::Model::DependencyDescription.new('RubyZip').addDescription( {
74
+ :Testers => [
75
+ {
76
+ :Type => 'RubyRequires',
77
+ :Content => [ 'zip/zipfilesystem' ]
78
+ }
79
+ ],
80
+ :Installers => [
81
+ {
82
+ :Type => 'Gem',
83
+ :Content => 'rubyzip',
84
+ :ContextModifiers => [
85
+ {
86
+ :Type => 'GemPath',
87
+ :Content => '%INSTALLDIR%'
88
+ }
89
+ ]
90
+ }
91
+ ]
92
+ } )
93
+ ]
94
+ )
95
+ if (!lIgnored.empty?)
96
+ rError = RuntimeError.new("Unable to install RubyZip without its dependencies (#{lIgnored.size} ignored dependencies).")
97
+ elsif (!lUnresolved.empty?)
98
+ rError = RuntimeError.new("Unable to install RubyZip without its dependencies (#{lUnresolved.size} unresolved dependencies):\n#{rError}")
99
+ end
100
+ end
101
+ end
102
+ if (rError == nil)
103
+ # Extract content of iFileName to iDirName
104
+ begin
105
+ # We don't put this require in the global scope as it needs first a DLL to be loaded by plugins
106
+ require 'zip/zipfilesystem'
107
+ Zip::ZipInputStream::open(iZipFileName) do |iZipFile|
108
+ while (lEntry = iZipFile.get_next_entry)
109
+ lDestFileName = "#{iDirName}/#{lEntry.name}"
110
+ if (lEntry.directory?)
111
+ FileUtils::mkdir_p(lDestFileName)
112
+ else
113
+ FileUtils::mkdir_p(File.dirname(lDestFileName))
114
+ # If the file already exist, first delete it to replace it with ours
115
+ if (File.exists?(lDestFileName))
116
+ File.unlink(lDestFileName)
117
+ end
118
+ lEntry.extract(lDestFileName)
119
+ end
120
+ end
121
+ end
122
+ rescue Exception
123
+ rError = $!
124
+ end
125
+ end
126
+
127
+ return rError
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,30 @@
1
+ #--
2
+ # Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ module RUtilAnts
7
+
8
+ module Platform
9
+
10
+ # OS constants
11
+ OS_WINDOWS = 0
12
+ OS_LINUX = 1
13
+
14
+ # Initialize the platform info
15
+ def self.initializePlatform
16
+ # Require the platform info
17
+ begin
18
+ require "RUtilAnts/Platforms/#{RUBY_PLATFORM}/PlatformInfo"
19
+ rescue Exception
20
+ logBug "Current platform #{RUBY_PLATFORM} is not supported."
21
+ raise RuntimeError, "Current platform #{RUBY_PLATFORM} is not supported."
22
+ end
23
+ # Create the corresponding object
24
+ $rUtilAnts_Platform_Info = PlatformInfo.new
25
+ Object.module_eval('include RUtilAnts::Platform')
26
+ end
27
+
28
+ end
29
+
30
+ end