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 .
21 //_______________________________________________
24 #include <jobs/shelljob.hxx>
25 #include <jobs/jobconst.hxx>
26 #include <threadhelp/readguard.hxx>
29 //_______________________________________________
32 #include <osl/file.hxx>
33 #include <osl/process.h>
34 #include <vcl/svapp.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/sequenceashashmap.hxx>
39 //_______________________________________________
42 #include <com/sun/star/util/PathSubstitution.hpp>
43 #include <com/sun/star/util/XStringSubstitution.hpp>
49 /** address job configuration inside argument set provided on method execute(). */
50 static const OUString
PROP_JOBCONFIG("JobConfig");
52 /** address job configuration property "Command". */
53 static const OUString
PROP_COMMAND("Command");
55 /** address job configuration property "Arguments". */
56 static const OUString
PROP_ARGUMENTS("Arguments");
58 /** address job configuration property "DeactivateJobIfDone". */
59 static const OUString
PROP_DEACTIVATEJOBIFDONE("DeactivateJobIfDone");
61 /** address job configuration property "CheckExitCode". */
62 static const OUString
PROP_CHECKEXITCODE("CheckExitCode");
64 //-----------------------------------------------
66 DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob
,
69 IMPLEMENTATIONNAME_SHELLJOB
)
71 DEFINE_INIT_SERVICE(ShellJob
,
74 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
75 to create a new instance of this class by our own supported service factory.
76 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
81 //-----------------------------------------------
82 ShellJob::ShellJob(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
88 //-----------------------------------------------
93 //-----------------------------------------------
94 css::uno::Any SAL_CALL
ShellJob::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lJobArguments
)
95 throw(css::lang::IllegalArgumentException
,
97 css::uno::RuntimeException
)
99 ::comphelper::SequenceAsHashMap
lArgs (lJobArguments
);
100 ::comphelper::SequenceAsHashMap
lOwnCfg(lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>()));
102 const OUString sCommand
= lOwnCfg
.getUnpackedValueOrDefault(PROP_COMMAND
, OUString());
103 const css::uno::Sequence
< OUString
> lCommandArguments
= lOwnCfg
.getUnpackedValueOrDefault(PROP_ARGUMENTS
, css::uno::Sequence
< OUString
>());
104 const ::sal_Bool bDeactivateJobIfDone
= lOwnCfg
.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE
, sal_True
);
105 const ::sal_Bool bCheckExitCode
= lOwnCfg
.getUnpackedValueOrDefault(PROP_CHECKEXITCODE
, sal_True
);
107 // replace all might existing place holder.
108 OUString sRealCommand
= impl_substituteCommandVariables(sCommand
);
110 // Command is required as minimum.
111 // If it does not exists ... we cant do our job.
112 // Deactivate such miss configured job silently .-)
113 if (sRealCommand
.isEmpty())
114 return ShellJob::impl_generateAnswer4Deactivation();
117 ::sal_Bool bDone
= impl_execute(sRealCommand
, lCommandArguments
, bCheckExitCode
);
119 return css::uno::Any();
121 // Job was done ... user configured deactivation of this job
123 if (bDeactivateJobIfDone
)
124 return ShellJob::impl_generateAnswer4Deactivation();
126 // There was no decision about deactivation of this job.
127 // So we have to return nothing here !
128 return css::uno::Any();
131 //-----------------------------------------------
132 css::uno::Any
ShellJob::impl_generateAnswer4Deactivation()
134 css::uno::Sequence
< css::beans::NamedValue
> aAnswer(1);
135 aAnswer
[0].Name
= JobConst::ANSWER_DEACTIVATE_JOB();
136 aAnswer
[0].Value
= css::uno::makeAny(sal_True
);
138 return css::uno::makeAny(aAnswer
);
141 //-----------------------------------------------
142 OUString
ShellJob::impl_substituteCommandVariables(const OUString
& sCommand
)
145 ReadGuard
aReadLock(m_aLock
);
146 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
152 css::uno::Reference
< css::uno::XComponentContext
> xContext( comphelper::getComponentContext(xSMGR
) );
153 css::uno::Reference
< css::util::XStringSubstitution
> xSubst( css::util::PathSubstitution::create(xContext
) );
154 const ::sal_Bool bSubstRequired
= sal_True
;
155 const OUString sCompleteCommand
= xSubst
->substituteVariables(sCommand
, bSubstRequired
);
157 return sCompleteCommand
;
159 catch(const css::uno::Exception
&)
165 //-----------------------------------------------
166 ::sal_Bool
ShellJob::impl_execute(const OUString
& sCommand
,
167 const css::uno::Sequence
< OUString
>& lArguments
,
168 ::sal_Bool bCheckExitCode
)
170 ::rtl_uString
** pArgs
= NULL
;
171 const ::sal_Int32 nArgs
= lArguments
.getLength ();
172 oslProcessOption nOptions
= osl_Process_WAIT
;
173 oslProcess
hProcess(0);
176 pArgs
= reinterpret_cast< ::rtl_uString
** >(const_cast< OUString
* >(lArguments
.getConstArray()));
178 oslProcessError eError
= osl_executeProcess(sCommand
.pData
, pArgs
, nArgs
, nOptions
, NULL
, NULL
, NULL
, 0, &hProcess
);
180 // executable not found or couldnt be started
181 if (eError
!= osl_Process_E_None
)
184 ::sal_Bool bRet
= sal_True
;
187 // check its return codes ...
188 oslProcessInfo aInfo
;
189 aInfo
.Size
= sizeof (oslProcessInfo
);
190 eError
= osl_getProcessInfo(hProcess
, osl_Process_EXITCODE
, &aInfo
);
192 if (eError
!= osl_Process_E_None
)
195 bRet
= (aInfo
.Code
== 0);
197 osl_freeProcessHandle(hProcess
);
201 } // namespace framework
203 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */