Class: TaskJuggler::SheetHandlerBase

Inherits:
Object
  • Object
show all
Defined in:
lib/taskjuggler/SheetHandlerBase.rb

Direct Known Subclasses

SheetReceiver, SheetSender

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(appName) ⇒ SheetHandlerBase

Returns a new instance of SheetHandlerBase.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 26

def initialize(appName)
  @appName = appName
  # User specific settings
  @emailDeliveryMethod = 'smtp'
  @smtpServer = nil
  @senderEmail = nil
  @workingDir = nil
  @scmCommand = nil
  # The default project ID
  @projectId = 'prj'

  # Controls the amount of output that is sent to the terminal.
  # 0: No output
  # 1: only errors
  # 2: errors and warnings
  # 3: All messages
  @outputLevel = 2
  # Controls the amount of information that is added to the log file. The
  # levels are identical to @outputLevel.
  @logLevel = 3
  # Set to true to not send any emails. Instead the email (header + body) is
  # printed to the terminal.
  @dryRun = false

  @logFile = 'timesheets.log'
  @emailFailure = false
end

Instance Attribute Details

#dryRunObject

Returns the value of attribute dryRun.



24
25
26
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 24

def dryRun
  @dryRun
end

#workingDirObject

Returns the value of attribute workingDir.



24
25
26
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 24

def workingDir
  @workingDir
end

Instance Method Details

#addToScm(message, fileName) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 110

def addToScm(message, fileName)
  return unless @scmCommand

  cmd = @scmCommand.gsub(/%m/, message)
  cmd.gsub!(/%f/, fileName)
  unless @dryRun
    `#{cmd}`
    if $? == 0
      info("Added #{fileName} to SCM")
    else
      error("SCM command #{cmd} failed: #{$?.class}")
    end
  end
end

#cutOut(text) ⇒ Object

Extract the text between the cut-marker lines and remove any email quotes from the beginnin of the line.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 56

def cutOut(text)
  # Pattern for the section start marker
  mark1 = /(.*)# --------8<--------8<--------/
  # Pattern for the section end marker
  mark2 = /# -------->8-------->8--------/
  # The cutOut section
  cutOutText = nil
  quoteLen = 0
  quoteMarks = emptyLine = +''
  text.each_line do |line|
    if cutOutText.nil?
      # We are looking for the line with the start marker (mark1)
      if (matches = mark1.match(line))
        quoteMarks = matches[1]
        quoteLen = quoteMarks.length
        # Special case for quoted empty lines without trailing spaces.
        emptyLine = quoteMarks.chomp.chomp(' ') + "\n"
        cutOutText = line[quoteLen..-1]
      end
    else
      # Remove quote marks from the beginning of the line.
      line = line[quoteLen..-1] if line[0, quoteLen] == quoteMarks
      line = "\n" if line == emptyLine

      cutOutText << line
      # We are gathering text until we hit the end marker (mark2)
      return cutOutText if mark2.match(line)
    end
  end

  # There are no cut markers. We just return the original text.
  text
end

#error(message) ⇒ Object

Raises:



135
136
137
138
139
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 135

def error(message)
  $stderr.puts message if @outputLevel >= 1
  log("ERROR", message) if @logLevel >= 1
  raise TjRuntimeError
end

#htmlMailBody(message) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 242

def htmlMailBody(message)
  html = HTMLDocument.new
  head = html.generateHead("TaskJuggler Report - #{@name}",
                           'description' => 'TaskJuggler Report',
                           'keywords' => 'taskjuggler, project, management')

  auxSrcDir = AppConfig.dataDirs('data/css')[0]
  cssFileName = (auxSrcDir ? auxSrcDir + '/tjreport.css' : '')
  # Raise an error if we haven't found the data directory
  if auxSrcDir.nil? || !File.exist?(cssFileName)
    dataDirError(cssFileName)
  end
  cssFile = IO.read(cssFileName)
  if cssFile.empty?
    raise TjException.new, <<"EOT"
Cannot read '#{cssFileName}'. Make sure the file is not empty and you have
read access permission.
EOT
  end
  head << XMLElement.new('meta', 'http-equiv' => 'Content-Style-Type',
                         'content' => 'text/css; charset=utf-8')
  head << (style = XMLElement.new('style', 'type' => 'text/css'))
  style << XMLBlob.new("\n" + cssFile)

  html.html << (body = XMLElement.new('body'))
  body << message.to_html

  html.to_s
end

#info(message) ⇒ Object



125
126
127
128
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 125

def info(message)
  puts message if @outputLevel >= 3
  log('INFO', message) if @logLevel >= 3
end

#log(type, message) ⇒ Object



141
142
143
144
145
146
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 141

def log(type, message)
  timeStamp = Time.new.strftime("%Y-%m-%d %H:%M:%S")
  File.open(@logFile, 'a') do |f|
    f.write("#{timeStamp} #{type} #{@appName}: #{message}\n")
  end
end

#sendEmail(to, subject, message, attachment = nil, from = nil, inReplyTo = nil) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 166

def sendEmail(to, subject, message, attachment = nil, from = nil,
              inReplyTo = nil)
  case @emailDeliveryMethod
  when 'smtp'
    settings_dto = {
        :address => @smtpServer,
        :port => 25,
    }
    Mail.defaults do
      delivery_method :smtp, settings_dto
    end
  when 'sendmail'
    Mail.defaults do
      delivery_method :sendmail
    end
  else
    raise "Unknown email delivery method: #{@emailDeliveryMethod}"
  end

  begin
    self_ = self
    mail = Mail.new do
      subject subject
      text_part do
        content_type [ 'text', 'plain', { 'charset' => 'UTF-8' } ]
        content_transfer_encoding 'base64'
        body message.to_s.to_base64
      end
      if message.is_a?(RichTextIntermediate)
        html_part do
          content_type 'text/html; charset=UTF-8'
          content_transfer_encoding 'base64'
          body self_.htmlMailBody(message).to_base64
        end
      end
    end
    mail.to = to
    mail.from = from || @senderEmail
    mail.in_reply_to = inReplyTo if inReplyTo
    mail['User-Agent'] = "#{AppConfig.softwareName}/#{AppConfig.version}"
    mail['X-TaskJuggler'] = @appName
    if attachment
      mail.add_file ({
        :filename => File.basename(attachment),
        :content => File.read(attachment)
      })
    end
    #raise "Mail header problem" unless mail.errors.empty?
  rescue
    @emailFailure = true
    error("Email processing failed: #{$!}")
  end

  if @dryRun
    # For testing and debugging, we only print out the email.
    puts "-- Email Start #{'-' * 60}\n#{mail.to_s}-- Email End #{'-' * 62}"
    log('INFO', "Show email '#{subject}' to #{to}")
  else
    # Actually send out the email.
    begin
      mail.deliver
    rescue
      # We try to send out another email. If that fails again, we abort
      # without further attempts.
      if @emailFailure
        log('ERROR', "Email double fault: #{$!}")
        raise TjRuntimeError
      else
        @emailFailure = true
        error("Email transmission failed: #{$!}")
      end
    end
    log('INFO', "Sent email '#{subject}' to #{to}")
  end
end

#sendRichTextEmail(to, subject, message, attachment = nil, from = nil, inReplyTo = nil) ⇒ Object

Like SheetHandlerBase::sendEmail but interpretes the message as RichText markup. The generated mail will have a text/plain and a text/html part.



151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 151

def sendRichTextEmail(to, subject, message, attachment = nil, from = nil,
                      inReplyTo = nil)
  rti = RichText.new(message).generateIntermediateFormat
  rti.lineWidth = 72
  rti.indent = 2
  rti.titleIndent = 0
  rti.listIndent = 2
  rti.parIndent = 2
  rti.preIndent = 4
  rti.sectionNumbers = false

  # Send out the email.
  sendEmail(to, subject, rti, attachment, from, inReplyTo)
end

#setWorkingDirObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 90

def setWorkingDir
  # Make sure the user has provided a properly setup config file.
  case @emailDeliveryMethod
  when 'smtp'
    error('\'smtpServer\' not configured') unless @smtpServer
  when 'sendmail'
    # nothing to check
  else
    error("Unknown emailDeliveryMethod #{@emailDeliveryMethod}")
  end
  error('\'senderEmail\' not configured') unless @senderEmail

  # Change into the specified working directory
  begin
    Dir.chdir(@workingDir) if @workingDir
  rescue
    error("Working directory #{@workingDir} not found")
  end
end

#warning(message) ⇒ Object



130
131
132
133
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 130

def warning(message)
  puts message if @outputLevel >= 2
  log('WARN', message) if @logLevel >= 2
end