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.



25
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
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 25

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.



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

def dryRun
  @dryRun
end

#workingDirObject

Returns the value of attribute workingDir.



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

def workingDir
  @workingDir
end

Instance Method Details

#addToScm(message, fileName) ⇒ Object



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

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.



55
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
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 55

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:



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

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

#htmlMailBody(message) ⇒ Object



240
241
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
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 240

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



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

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

#log(type, message) ⇒ Object



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

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



165
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
# File 'lib/taskjuggler/SheetHandlerBase.rb', line 165

def sendEmail(to, subject, message, attachment = nil, from = nil,
              inReplyTo = nil)
  case @emailDeliveryMethod
  when 'smtp'
    Mail.defaults do
      delivery_method :smtp, {
        :address => @smtpServer,
        :port => 25
      }
    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.



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

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



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

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



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

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