Separated code to have a lib and an example. Improved design, fixed a few issues related to folder location. This is still experimental and require more work to be really friendly to use.
198 lines
4.4 KiB
Plaintext
198 lines
4.4 KiB
Plaintext
note
|
|
description : "Objects that ..."
|
|
author : "$Author$"
|
|
date : "$Date$"
|
|
revision : "$Revision$"
|
|
|
|
class
|
|
CMS_EXTERNAL_MAILER
|
|
|
|
inherit
|
|
CMS_MAILER
|
|
|
|
-- SHARED_EXECUTION_ENVIRONMENT
|
|
|
|
create
|
|
make
|
|
|
|
feature {NONE} -- Initialization
|
|
|
|
make (a_exe: like executable_path; args: detachable ITERABLE [READABLE_STRING_8])
|
|
-- Initialize `Current'.
|
|
do
|
|
set_parameters (a_exe, args)
|
|
end
|
|
|
|
executable_path: READABLE_STRING_8
|
|
|
|
arguments: detachable ARRAYED_LIST [STRING_8]
|
|
|
|
stdin_mode_set: BOOLEAN
|
|
-- Use `stdin' to pass email message, rather than using local file?
|
|
|
|
stdin_termination_sequence: detachable STRING
|
|
-- Termination sequence for the stdin mode
|
|
--| If any, this tells the executable all the data has been provided
|
|
--| For instance, using sendmail, you should have "%N.%N%N"
|
|
|
|
feature -- Status
|
|
|
|
is_available: BOOLEAN
|
|
local
|
|
f: RAW_FILE
|
|
do
|
|
create f.make (executable_path)
|
|
Result := f.exists
|
|
end
|
|
|
|
feature -- Change
|
|
|
|
set_parameters (cmd: like executable_path; args: detachable ITERABLE [READABLE_STRING_8])
|
|
-- Set parameters `executable_path' and associated `arguments'
|
|
local
|
|
l_args: like arguments
|
|
do
|
|
executable_path := cmd
|
|
if args = Void then
|
|
arguments := Void
|
|
else
|
|
create l_args.make (5)
|
|
across
|
|
args as c
|
|
loop
|
|
l_args.force (c.item)
|
|
end
|
|
arguments := l_args
|
|
end
|
|
end
|
|
|
|
set_stdin_mode (b: BOOLEAN; v: like stdin_termination_sequence)
|
|
-- Set the `stdin_mode_set' value
|
|
-- and provide optional termination sequence when stdin mode is selected.
|
|
do
|
|
stdin_mode_set := b
|
|
stdin_termination_sequence := v
|
|
end
|
|
|
|
feature -- Basic operation
|
|
|
|
process_email (a_email: CMS_EMAIL)
|
|
local
|
|
l_factory: PROCESS_FACTORY
|
|
args: like arguments
|
|
p: detachable PROCESS
|
|
retried: INTEGER
|
|
do
|
|
if retried = 0 then
|
|
create l_factory
|
|
if stdin_mode_set then
|
|
p := l_factory.process_launcher (executable_path, arguments, Void)
|
|
p.set_hidden (True)
|
|
p.set_separate_console (False)
|
|
|
|
p.redirect_input_to_stream
|
|
p.launch
|
|
if p.launched then
|
|
p.put_string (a_email.message)
|
|
if attached stdin_termination_sequence as v then
|
|
p.put_string (v)
|
|
end
|
|
end
|
|
else
|
|
if attached arguments as l_args then
|
|
args := l_args.twin
|
|
else
|
|
if attached {RAW_FILE} new_temporary_file (generator) as f then
|
|
f.create_read_write
|
|
f.put_string (a_email.message)
|
|
f.close
|
|
create args.make (1)
|
|
args.force (f.name)
|
|
end
|
|
end
|
|
p := l_factory.process_launcher (executable_path, args, Void)
|
|
p.set_hidden (True)
|
|
p.set_separate_console (False)
|
|
|
|
p.launch
|
|
end
|
|
if p.launched and not p.has_exited then
|
|
p.wait_for_exit_with_timeout (1_000_000)
|
|
if not p.has_exited then
|
|
p.terminate
|
|
if not p.has_exited then
|
|
p.wait_for_exit_with_timeout (1_000_000)
|
|
end
|
|
end
|
|
end
|
|
elseif retried = 1 then
|
|
if p /= Void and then p.launched and then not p.has_exited then
|
|
p.terminate
|
|
if not p.has_exited then
|
|
p.wait_for_exit_with_timeout (1_000_000)
|
|
end
|
|
end
|
|
end
|
|
rescue
|
|
retried := retried + 1
|
|
retry
|
|
end
|
|
|
|
feature {NONE} -- Implementation
|
|
|
|
new_temporary_file (a_extension: detachable STRING_8): RAW_FILE
|
|
-- Create file with temporary name.
|
|
-- With concurrent execution, noting ensures that {FILE_NAME}.make_temporary_name is unique
|
|
-- So using `a_extension' may help
|
|
local
|
|
fn: FILE_NAME
|
|
s: like {FILE_NAME}.string
|
|
f: detachable like new_temporary_file
|
|
i: INTEGER
|
|
do
|
|
-- With concurrent execution, nothing ensures that {FILE_NAME}.make_temporary_name is unique
|
|
-- So let's try to find
|
|
from
|
|
until
|
|
f /= Void or i > 1000
|
|
loop
|
|
create fn.make_temporary_name
|
|
s := fn.string
|
|
if i > 0 then
|
|
s.append_character ('-')
|
|
s.append_integer (i)
|
|
create fn.make_from_string (s)
|
|
end
|
|
if a_extension /= Void then
|
|
fn.add_extension (a_extension)
|
|
end
|
|
s := fn.string
|
|
create f.make (fn.string)
|
|
if f.exists then
|
|
i := i + 1
|
|
f := Void
|
|
end
|
|
end
|
|
if f = Void then
|
|
Result := new_temporary_file (Void)
|
|
else
|
|
Result := f
|
|
check not_temporary_file_exists: not Result.exists end
|
|
check temporary_creatable: Result.is_creatable end
|
|
end
|
|
ensure
|
|
not_result_exists: not Result.exists
|
|
result_creatable: Result.is_creatable
|
|
end
|
|
|
|
feature {NONE} -- Environment
|
|
|
|
Execution_environment: EXECUTION_ENVIRONMENT
|
|
once
|
|
create Result
|
|
end
|
|
|
|
invariant
|
|
|
|
end
|