libisi 0.3.0

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.
Files changed (91) hide show
  1. data/LICENSE +677 -0
  2. data/Manifest +89 -0
  3. data/Rakefile +34 -0
  4. data/lib/inifile.rb +119 -0
  5. data/lib/libisi.rb +948 -0
  6. data/lib/libisi/attribute.rb +32 -0
  7. data/lib/libisi/attribute/activerecord.rb +34 -0
  8. data/lib/libisi/attribute/base.rb +33 -0
  9. data/lib/libisi/base.rb +109 -0
  10. data/lib/libisi/bridge.rb +21 -0
  11. data/lib/libisi/bridge/base.rb +23 -0
  12. data/lib/libisi/bridge/java.rb +71 -0
  13. data/lib/libisi/bridge/python.rb +37 -0
  14. data/lib/libisi/cache.rb +21 -0
  15. data/lib/libisi/cache/base.rb +67 -0
  16. data/lib/libisi/cache/file_cache.rb +24 -0
  17. data/lib/libisi/chart.rb +21 -0
  18. data/lib/libisi/chart/base.rb +320 -0
  19. data/lib/libisi/chart/jfreechart.rb +682 -0
  20. data/lib/libisi/chart/jfreechart_generator.rb +206 -0
  21. data/lib/libisi/color.rb +21 -0
  22. data/lib/libisi/color/base.rb +66 -0
  23. data/lib/libisi/color/colortools.rb +92 -0
  24. data/lib/libisi/color/java.rb +44 -0
  25. data/lib/libisi/concept.rb +33 -0
  26. data/lib/libisi/concept/activerecord.rb +39 -0
  27. data/lib/libisi/concept/base.rb +58 -0
  28. data/lib/libisi/doc.rb +35 -0
  29. data/lib/libisi/doc/base.rb +414 -0
  30. data/lib/libisi/doc/html.rb +85 -0
  31. data/lib/libisi/doc/text.rb +98 -0
  32. data/lib/libisi/doc/wiki.rb +55 -0
  33. data/lib/libisi/environment.rb +21 -0
  34. data/lib/libisi/environment/base.rb +36 -0
  35. data/lib/libisi/environment/http.rb +105 -0
  36. data/lib/libisi/environment/rails.rb +27 -0
  37. data/lib/libisi/environment/root.rb +23 -0
  38. data/lib/libisi/fake_logger/logger.rb +61 -0
  39. data/lib/libisi/function/base.rb +30 -0
  40. data/lib/libisi/hal.rb +558 -0
  41. data/lib/libisi/instance.rb +27 -0
  42. data/lib/libisi/instance/activerecord.rb +21 -0
  43. data/lib/libisi/instance/base.rb +42 -0
  44. data/lib/libisi/log.rb +237 -0
  45. data/lib/libisi/mail/base.rb +32 -0
  46. data/lib/libisi/mail/tmail.rb +120 -0
  47. data/lib/libisi/parameter/base.rb +41 -0
  48. data/lib/libisi/property.rb +27 -0
  49. data/lib/libisi/property/base.rb +28 -0
  50. data/lib/libisi/reciever/base.rb +31 -0
  51. data/lib/libisi/reciever/socket.rb +31 -0
  52. data/lib/libisi/relation.rb +23 -0
  53. data/lib/libisi/request.rb +22 -0
  54. data/lib/libisi/request/base.rb +29 -0
  55. data/lib/libisi/request/http.rb +129 -0
  56. data/lib/libisi/response/base.rb +27 -0
  57. data/lib/libisi/task/base.rb +27 -0
  58. data/lib/libisi/task/http.rb +90 -0
  59. data/lib/libisi/tee.rb +296 -0
  60. data/lib/libisi/ui/base.rb +116 -0
  61. data/lib/libisi/ui/console.rb +238 -0
  62. data/lib/libisi/ui/kde.rb +94 -0
  63. data/lib/libisi/ui/nobody.rb +29 -0
  64. data/lib/libisi/ui/rails.rb +150 -0
  65. data/lib/libisi/ui/x11.rb +55 -0
  66. data/lib/libisi/uri.rb +42 -0
  67. data/lib/libisi/uri/activerecord.rb +152 -0
  68. data/lib/libisi/uri/base.rb +115 -0
  69. data/lib/libisi/uri/file.rb +43 -0
  70. data/lib/libisi/uri/ldap.rb +72 -0
  71. data/lib/libisi/uri/mysql.rb +98 -0
  72. data/lib/libisi/value.rb +31 -0
  73. data/lib/libisi/value/attribute_value.rb +19 -0
  74. data/lib/libisi/value/base.rb +55 -0
  75. data/lib/libisi/value/property_value.rb +19 -0
  76. data/lib/libisi/value/relation_value.rb +19 -0
  77. data/lib/ordered_hash.rb +228 -0
  78. data/libisi.gemspec +31 -0
  79. data/test/bridge_test.rb +77 -0
  80. data/test/cache_test.rb +65 -0
  81. data/test/chart_test.rb +179 -0
  82. data/test/color_test.rb +64 -0
  83. data/test/concept_test.rb +56 -0
  84. data/test/doc_test.rb +172 -0
  85. data/test/fixtures/test.db +0 -0
  86. data/test/ordered_hash_test.rb +39 -0
  87. data/test/profile_test.rb +36 -0
  88. data/test/request_test.rb +121 -0
  89. data/test/test +0 -0
  90. data/test/ui_test.rb +62 -0
  91. metadata +244 -0
@@ -0,0 +1,27 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/base.rb"
19
+ require "libisi/instance/base.rb"
20
+ class Instance < Base
21
+
22
+ def self.create(object, options = {})
23
+ concept = Concept.create(object.class)
24
+ BaseInstance.new(concept, object, options)
25
+ end
26
+
27
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class ActiverecordInstance
19
+
20
+
21
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/value"
19
+ class BaseInstance
20
+
21
+ attr_reader :concept, :object
22
+
23
+ def initialize(concept, object, options = {})
24
+ @concept = concept
25
+ @object = object
26
+ end
27
+
28
+ def value(name, options = {})
29
+ values.first {|v| v.name == name}
30
+ end
31
+
32
+ def values(options = {})
33
+
34
+ if options[:type]
35
+ sources = concept.send(options[:type], options)
36
+ return sources.map {|a| Value.create(a, object)}
37
+ end
38
+
39
+ concept.value_accessors.map {|a| Value.create(a, object)}
40
+ end
41
+
42
+ end
data/lib/libisi/log.rb ADDED
@@ -0,0 +1,237 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/base.rb"
19
+ require "log4r"
20
+ require 'log4r/configurator'
21
+
22
+ class Log < Base
23
+ LOG_FORMAT = "[%l] %d :: %m"
24
+ PRINT_DEBUG = false
25
+
26
+ def self.output_types
27
+ {"log" => ["err","error","debug","dbg","log"]}
28
+ end
29
+
30
+ def self.create_output(type, ending, file)
31
+ name = file.basename.to_s
32
+ case ending
33
+ when "err","error"
34
+ new_logger(name, file.to_s, :level => Logger::ERROR)
35
+ when "debug","dbg"
36
+ new_logger(name, file.to_s, :level => Logger::DEBUG)
37
+ when "log"
38
+ new_logger(name, file.to_s, :level => stdout_log_level)
39
+ else
40
+ raise "Unexpected ending #{ending}"
41
+ end
42
+ end
43
+
44
+
45
+ def self.redefine_logger(options)
46
+ options[:redefine] ||= true
47
+ init(options)
48
+ end
49
+
50
+ def self.normalize_level(level)
51
+ level = level.to_s if level.class == Symbol
52
+ level = case level
53
+ when String, Symbol
54
+ Log4r.const_get(level.to_s.upcase)
55
+ when Fixnum
56
+ level
57
+ when NilClass
58
+ nil
59
+ else
60
+ raise "Unexpected log level class #{level.class} #{level.inspect}"
61
+ end
62
+ print "Normalized log level is #{level}\n" if PRINT_DEBUG
63
+ level
64
+ end
65
+
66
+ def self.init(options = {})
67
+ #raise "Logging already initialized" if $log and !options[:redefine]
68
+ $log.debug("Redefine logger #{options.inspect}") if $log
69
+
70
+ # if defined?(RAILS_DEFAULT_LOGGER) and !options[:output]
71
+ # logfile = RAILS_DEFAULT_LOGGER.instance_eval("@log")
72
+ # raise "Cannot handle rails log destination #{logfile.class}" unless
73
+ # logfile.class == File
74
+ # RAILS_DEFAULT_LOGGER.info("Going to replace RAILS_DEFAULT_LOGGER by libisis own logger")
75
+ # options[:output] ||= logfile
76
+ # end
77
+
78
+ case options[:logging]
79
+ when nil, "Log4r", "log4r"
80
+ require "log4r"
81
+
82
+ # Initialize base logging
83
+ Log4r::Configurator.custom_levels(*options[:log_levels]) if options[:log_levels] and !options[:redefine]
84
+ # we need this to that log levels are initialized
85
+ Log4r::Logger.new("default")
86
+
87
+ options[:level] ||= (self.log_level_name or
88
+ (defined?(LOG_LEVEL) and LOG_LEVEL) or
89
+ ENV["LOG_LEVEL"] or "warn")
90
+ options[:level] = normalize_level(options[:level])
91
+
92
+ # new version: default_output = $environment.default_log_output
93
+ default_output = :stdout
94
+ options[:output] = nil if (options[:output].class == Array and options[:output].length == 0)
95
+ options[:output] ||= ((defined?(LOG_OUTPUT) and LOG_OUTPUT) or
96
+ ENV["LOG_OUTPUT"] or
97
+ default_output)
98
+ options[:output] = :stdout if options[:output] == "stdout"
99
+ options[:output] = [options[:output]] if options[:output].class != Array
100
+
101
+ $log.debug{"Create new logger now with Updated options: #{options.inspect}"} if $log
102
+
103
+ if !options[:redefine] or $log.nil? # new version: or $log.class == Libisi::Logging::FunctionCallLogger
104
+ $log = Log4r::Logger.new((ENV["PROGRAM_IDENT"] or "default"))
105
+ else
106
+ #$log.instance_variable_set("@outputters",[])
107
+ #$log.outputters.each {|o| $log.remove(o.name)}
108
+ $log.outputters = []
109
+ raise "Still outputters, maybe /usr/lib/ruby/1.8/logger.rb loaded" if $log.outputters.length != 0
110
+ @outputs = []
111
+ end
112
+
113
+ options[:output].each_with_index {|output, i|
114
+ new_logger("default#{i}", (output or :stdout), options)
115
+ }
116
+ else
117
+ raise "Unexpected logging mode #{options[:logging]}"
118
+ end
119
+
120
+
121
+ self.log_level = options[:level]
122
+ $log.debug("Logging initialized #{options.inspect}")
123
+ $log.outputters.each {|o| $log.debug("Outputter: #{o.inspect}") } if $log.debug?
124
+ end
125
+
126
+ def self.outputs; @outputs or []; end
127
+ def self.new_logger(name, output, options = {})
128
+ raise "No outputter given." unless output
129
+ new_outputters = []
130
+ case output
131
+ when String, Pathname
132
+ new_outputters << Log4r::FileOutputter.new(name,:filename => output.to_s)
133
+ when :stdout
134
+ $stdout_logger||= Log4r::Outputter.stdout
135
+ $stderr_logger||= Log4r::Outputter.stderr
136
+ new_outputters << $stdout_logger
137
+ new_outputters << $stderr_logger
138
+ when :stderr
139
+ $stderr_logger||= Log4r::Outputter.stderr
140
+ new_outputters << $stderr_logger
141
+ when Hash
142
+ raise "unexpected output type #{output.inspect}"
143
+ else
144
+ new_outputters << Log4r::IOOutputter.new(name, output)
145
+ end
146
+
147
+ pattern = Log4r::PatternFormatter.new(:pattern => (options[:pattern] or LOG_FORMAT))
148
+
149
+ new_outputters.each_with_index {|out,i|
150
+ raise "Outputter #{i} is nil" unless out
151
+ old_len = $log.outputters.length
152
+ $log.add(out)
153
+ raise "No outputter added, maybe /usr/lib/ruby/1.8/logger.rb loaded" unless $log.outputters.length == (old_len + 1)
154
+ @outputs ||= []
155
+ @outputs << output
156
+ out.formatter = pattern
157
+
158
+ #normalize option
159
+ options[:only] = normalize_level(options[:only])
160
+ options[:level] = ((normalize_level(options[:level]) or $log.level))
161
+
162
+ # stderr level is always error
163
+ # and already defined
164
+ if output == :stdout
165
+ next if out == $stderr_logger
166
+ raise "Only log level not allowed for :stdout" if options[:only]
167
+ self.stdout_log_level = options[:level]
168
+ next
169
+ end
170
+
171
+ if options[:only]
172
+ out.only_at(options[:only])
173
+ $log.level = options[:only] if $log.level > options[:only]
174
+ end
175
+ if (options[:level])
176
+ out.level = options[:level]
177
+ $log.level = options[:level] if $log.level > options[:level]
178
+ end
179
+ }
180
+
181
+ print "Added new logger at #{output.inspect} (#{options.inspect})\n" if PRINT_DEBUG
182
+ $log.debug{"Added new logger at #{output.inspect} (#{options.inspect})"}
183
+ end
184
+
185
+ # LOGGING LEVELS
186
+ def self.log_level=(level)
187
+ $log.debug("Setting log_level #{level} (DEBUG is #{Log4r::DEBUG})")
188
+
189
+ $log.level = level
190
+ $log.outputters.each {|o|
191
+ next if o == $stdout_logger or o == $stderr_logger
192
+ o.level = level
193
+ }
194
+ self.stdout_log_level = level if $stdout_logger
195
+ @log_level = level
196
+ print "Log level is now #{$log.level} (set #{level})\n" if PRINT_DEBUG
197
+ $log.debug("Log level is now #{log_level_name}")
198
+ end
199
+ def self.log_level
200
+ @log_level ||= Log4r::WARN
201
+ @log_level
202
+ end
203
+ def self.log_level_name
204
+ return nil unless self.log_level
205
+ return nil unless defined?(Log4r::LNAMES)
206
+ Log4r::LNAMES[self.log_level]
207
+ end
208
+
209
+ def self.stdout_log_level
210
+ self.log_level
211
+ end
212
+ def self.stdout_log_level=(level)
213
+ return unless outputs.include?(:stdout)
214
+ print "set stdout level #{level} debug is: #{Log4r::DEBUG}\n" if PRINT_DEBUG
215
+ print "stdout_err_level: #{$stderr_logger.level}\n" if PRINT_DEBUG
216
+ print "stdout_log_level: #{$stdout_logger.level}\n" if PRINT_DEBUG
217
+ $stderr_logger.level = Log4r::ERROR
218
+ print "stderr_level: #{$stderr_logger.level}\n" if PRINT_DEBUG
219
+
220
+ raise "Level #{level} is too verbose" if level == 0
221
+ raise "Level #{level} is too quiet" if level >= Log4r::LEVELS - 2
222
+ if level >= (Log4r::LEVELS - 3)
223
+ $log.debug("Removing stdout logger")
224
+ $log.remove($stdout_logger.name)
225
+ print "removed stdout_logger\n" if PRINT_DEBUG
226
+ else
227
+ unless $log.outputters.include?($stdout_logger)
228
+ print "Added stdout_logger\n" if PRINT_DEBUG
229
+ $log.add($stdout_logger)
230
+ end
231
+ levels = (level..Log4r::LEVELS-4).to_a
232
+ print "Stdout levels: #{levels.inspect}\n" if PRINT_DEBUG
233
+ $stdout_logger.only_at(*levels)
234
+ end
235
+ end
236
+
237
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class BaseMail
19
+
20
+ def default_from
21
+ "#{program_name.inspect} <#{user}@#{full_qualified_domainname}>"
22
+ end
23
+ def default_subject
24
+ "Email from #{program_name.inspect} on #{full_qualified_domainname} by #{user}"
25
+ end
26
+
27
+ def send_email(recipients, text, options = {}); send_mail(recipients, text, options); end
28
+ def send_mail(recipients, text, options = {})
29
+ raise "not implemented"
30
+ end
31
+
32
+ end
@@ -0,0 +1,120 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'tmail'
19
+ require 'libisi/mail/base'
20
+ require 'net/smtp'
21
+ require 'base64'
22
+
23
+ # bugfix
24
+ module TMail
25
+ module TextUtils
26
+ private
27
+ def random_tag
28
+ @@uniq += 1
29
+ t = Time.now
30
+ sprintf('%x%x_%x%x%d%x',
31
+ t.to_i, t.tv_usec,
32
+ $$, Thread.current.object_id, @@uniq, rand(255))
33
+ # was
34
+ # $$, Thread.current.id, @@uniq, rand(255))
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+ class TMailMail < BaseMail
41
+
42
+ def send_mail(recipients, text, options = {})
43
+ mail = TMail::Mail.new()
44
+ mail.date = Time.now
45
+ mail.to = recipients
46
+ mail.from = (options[:from] or self.default_from)
47
+ mail.subject = (options[:subject] or self.default_subject)
48
+ if (ccs = options[:cc])
49
+ $log.debug("Sending mail cc to #{ccs.inspect}")
50
+ mail.cc = ccs
51
+ end
52
+
53
+ if (bccs = options[:bcc])
54
+ $log.debug("Sending mail bcc to #{bccs.inspect}")
55
+ mail.bcc = bccs
56
+ end
57
+
58
+ mail.mime_version = "1.0"
59
+
60
+ text = text.readlines.join("\n") if text.respond_to?(:readlines)
61
+ if text =~ /\<html/
62
+ # for html
63
+ $log.debug("Expecting text has content type html")
64
+ mail.parts.push(create_text_part(text, "html"))
65
+ else
66
+ $log.debug("Expecting text has content type text")
67
+ mail.parts.push(create_text_part(text))
68
+ end
69
+
70
+ (options[:attachments] or []).each {|a|
71
+ mail.parts.push(create_attachment(a))
72
+ }
73
+
74
+ # this have to be after parts has been added, otherwisse
75
+ # "can't convert nil into String" will be thrown on adding parts
76
+ mail.set_content_type( 'multipart', 'mixed' )
77
+ mail.message_id = TMail.new_message_id(full_qualified_domainname)
78
+
79
+ Net::SMTP.start("localhost",25) do |smtpclient|
80
+ $log.info("Sending mail with subject #{mail.subject.to_s.inspect} to #{mail.to.to_s.inspect}")
81
+ smtpclient.send_message(mail.to_s, mail.from, mail.to)
82
+ end
83
+ end
84
+
85
+ def create_text_part(text, content_type = "plain")
86
+ text_part = TMail::Mail.new
87
+ text_part.body = text
88
+ text_part.charset = 'utf-8'
89
+ text_part.transfer_encoding = '7bit'
90
+ text_part.set_content_type('text', content_type)
91
+ text_part
92
+ end
93
+
94
+ def create_attachment(file_name)
95
+ file = Pathname.new(file_name)
96
+ raise "File not readable: #{file_name}" unless file.readable?
97
+ $log.info("Creating attachment #{file_name}")
98
+ attachment = TMail::Mail.new
99
+ if file_name =~ /bz2/ or file_name =~ /bzip2/
100
+ attachment.body = Base64.encode64(Pathname.new(file_name).readlines.join)
101
+ file_name = file.basename
102
+ else
103
+ $log.info("Compressing attachment to bz2")
104
+ command = "|cat #{file_name.to_s.inspect} | bzip2"
105
+ $log.debug{"Compression command is: #{command.inspect}"}
106
+ compr = open(command) {|f| f.readlines.join}
107
+ raise "Error compressing attachment." unless $?.success?
108
+ $log.info("Compressed file has length #{compr.length}")
109
+ attachment.body = Base64.encode64(compr)
110
+ file_name = "#{file.basename}.bz2"
111
+ end
112
+
113
+ $log.debug("Attaching file #{file_name}")
114
+ attachment.transfer_encoding = '7bit'
115
+ attachment.encoding = 'base64'
116
+ attachment.set_content_type('application', 'x-bzip', 'name' => "#{file_name.to_s}")
117
+ attachment.header["Content-Disposition"] = "attachment; filename=#{file_name.to_s}"
118
+ attachment
119
+ end
120
+ end