1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <jobs/shelljob.hxx>
23 #include <jobs/jobconst.hxx>
28 #include <osl/file.hxx>
29 #include <osl/process.h>
30 #include <vcl/svapp.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/sequenceashashmap.hxx>
37 #include <com/sun/star/util/PathSubstitution.hpp>
38 #include <com/sun/star/util/XStringSubstitution.hpp>
42 /** address job configuration inside argument set provided on method execute(). */
43 static const char PROP_JOBCONFIG
[] = "JobConfig";
45 /** address job configuration property "Command". */
46 static const char PROP_COMMAND
[] = "Command";
48 /** address job configuration property "Arguments". */
49 static const char PROP_ARGUMENTS
[] = "Arguments";
51 /** address job configuration property "DeactivateJobIfDone". */
52 static const char PROP_DEACTIVATEJOBIFDONE
[] = "DeactivateJobIfDone";
54 /** address job configuration property "CheckExitCode". */
55 static const char PROP_CHECKEXITCODE
[] = "CheckExitCode";
57 DEFINE_XSERVICEINFO_MULTISERVICE_2(ShellJob
,
60 IMPLEMENTATIONNAME_SHELLJOB
)
62 DEFINE_INIT_SERVICE(ShellJob
,
65 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
66 to create a new instance of this class by our own supported service factory.
67 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
72 ShellJob::ShellJob(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
73 : m_xContext (xContext
)
81 css::uno::Any SAL_CALL
ShellJob::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lJobArguments
)
82 throw(css::lang::IllegalArgumentException
,
84 css::uno::RuntimeException
, std::exception
)
86 ::comphelper::SequenceAsHashMap
lArgs (lJobArguments
);
87 ::comphelper::SequenceAsHashMap
lOwnCfg(lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>()));
89 const OUString sCommand
= lOwnCfg
.getUnpackedValueOrDefault(PROP_COMMAND
, OUString());
90 const css::uno::Sequence
< OUString
> lCommandArguments
= lOwnCfg
.getUnpackedValueOrDefault(PROP_ARGUMENTS
, css::uno::Sequence
< OUString
>());
91 const bool bDeactivateJobIfDone
= lOwnCfg
.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE
, true );
92 const bool bCheckExitCode
= lOwnCfg
.getUnpackedValueOrDefault(PROP_CHECKEXITCODE
, true );
94 // replace all might existing place holder.
95 OUString sRealCommand
= impl_substituteCommandVariables(sCommand
);
97 // Command is required as minimum.
98 // If it does not exists ... we can't do our job.
99 // Deactivate such miss configured job silently .-)
100 if (sRealCommand
.isEmpty())
101 return ShellJob::impl_generateAnswer4Deactivation();
104 bool bDone
= impl_execute(sRealCommand
, lCommandArguments
, bCheckExitCode
);
106 return css::uno::Any();
108 // Job was done ... user configured deactivation of this job
110 if (bDeactivateJobIfDone
)
111 return ShellJob::impl_generateAnswer4Deactivation();
113 // There was no decision about deactivation of this job.
114 // So we have to return nothing here !
115 return css::uno::Any();
118 css::uno::Any
ShellJob::impl_generateAnswer4Deactivation()
120 css::uno::Sequence
< css::beans::NamedValue
> aAnswer(1);
121 aAnswer
[0].Name
= JobConst::ANSWER_DEACTIVATE_JOB();
122 aAnswer
[0].Value
= css::uno::makeAny(sal_True
);
124 return css::uno::makeAny(aAnswer
);
127 OUString
ShellJob::impl_substituteCommandVariables(const OUString
& sCommand
)
131 css::uno::Reference
< css::util::XStringSubstitution
> xSubst( css::util::PathSubstitution::create(m_xContext
) );
132 const bool bSubstRequired
= true;
133 const OUString sCompleteCommand
= xSubst
->substituteVariables(sCommand
, bSubstRequired
);
135 return sCompleteCommand
;
137 catch(const css::uno::Exception
&)
143 bool ShellJob::impl_execute(const OUString
& sCommand
,
144 const css::uno::Sequence
< OUString
>& lArguments
,
147 ::rtl_uString
** pArgs
= NULL
;
148 const ::sal_Int32 nArgs
= lArguments
.getLength ();
149 oslProcessOption nOptions
= osl_Process_WAIT
;
150 oslProcess
hProcess(0);
153 pArgs
= reinterpret_cast< ::rtl_uString
** >(const_cast< OUString
* >(lArguments
.getConstArray()));
155 oslProcessError eError
= osl_executeProcess(sCommand
.pData
, pArgs
, nArgs
, nOptions
, NULL
, NULL
, NULL
, 0, &hProcess
);
157 // executable not found or couldnt be started
158 if (eError
!= osl_Process_E_None
)
164 // check its return codes ...
165 oslProcessInfo aInfo
;
166 aInfo
.Size
= sizeof (oslProcessInfo
);
167 eError
= osl_getProcessInfo(hProcess
, osl_Process_EXITCODE
, &aInfo
);
169 if (eError
!= osl_Process_E_None
)
172 bRet
= (aInfo
.Code
== 0);
174 osl_freeProcessHandle(hProcess
);
178 } // namespace framework
180 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */