1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shelljob.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_______________________________________________
37 #include <jobs/shelljob.hxx>
38 #include <jobs/jobconst.hxx>
39 #include <threadhelp/readguard.hxx>
42 //_______________________________________________
45 #include <osl/file.hxx>
46 #include <osl/process.h>
47 #include <vcl/svapp.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <comphelper/sequenceashashmap.hxx>
51 //_______________________________________________
54 #include <com/sun/star/system/XSystemShellExecute.hpp>
55 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
56 #include <com/sun/star/util/XStringSubstitution.hpp>
58 //_______________________________________________
63 //_______________________________________________
66 /** adress job configuration inside argument set provided on method execute(). */
67 static const ::rtl::OUString PROP_JOBCONFIG
= ::rtl::OUString::createFromAscii("JobConfig");
69 /** adress job configuration property "Command". */
70 static const ::rtl::OUString PROP_COMMAND
= ::rtl::OUString::createFromAscii("Command");
72 /** adress job configuration property "Arguments". */
73 static const ::rtl::OUString PROP_ARGUMENTS
= ::rtl::OUString::createFromAscii("Arguments");
75 /** adress job configuration property "DeactivateJobIfDone". */
76 static const ::rtl::OUString PROP_DEACTIVATEJOBIFDONE
= ::rtl::OUString::createFromAscii("DeactivateJobIfDone");
78 /** adress job configuration property "CheckExitCode". */
79 static const ::rtl::OUString PROP_CHECKEXITCODE
= ::rtl::OUString::createFromAscii("CheckExitCode");
81 //-----------------------------------------------
83 DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob
,
86 IMPLEMENTATIONNAME_SHELLJOB
)
88 DEFINE_INIT_SERVICE(ShellJob
,
91 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
92 to create a new instance of this class by our own supported service factory.
93 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
98 //-----------------------------------------------
99 ShellJob::ShellJob(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
105 //-----------------------------------------------
106 ShellJob::~ShellJob()
110 //-----------------------------------------------
111 css::uno::Any SAL_CALL
ShellJob::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lJobArguments
)
112 throw(css::lang::IllegalArgumentException
,
113 css::uno::Exception
,
114 css::uno::RuntimeException
)
116 ::comphelper::SequenceAsHashMap
lArgs (lJobArguments
);
117 ::comphelper::SequenceAsHashMap
lOwnCfg(lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>()));
119 const ::rtl::OUString sCommand
= lOwnCfg
.getUnpackedValueOrDefault(PROP_COMMAND
, ::rtl::OUString());
120 const css::uno::Sequence
< ::rtl::OUString
> lCommandArguments
= lOwnCfg
.getUnpackedValueOrDefault(PROP_ARGUMENTS
, css::uno::Sequence
< ::rtl::OUString
>());
121 const ::sal_Bool bDeactivateJobIfDone
= lOwnCfg
.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE
, sal_True
);
122 const ::sal_Bool bCheckExitCode
= lOwnCfg
.getUnpackedValueOrDefault(PROP_CHECKEXITCODE
, sal_True
);
124 // replace all might existing place holder.
125 ::rtl::OUString sRealCommand
= impl_substituteCommandVariables(sCommand
);
127 // Command is required as minimum.
128 // If it does not exists ... we cant do our job.
129 // Deactivate such miss configured job silently .-)
130 if (sRealCommand
.getLength() < 1)
131 return ShellJob::impl_generateAnswer4Deactivation();
134 ::sal_Bool bDone
= impl_execute(sRealCommand
, lCommandArguments
, bCheckExitCode
);
136 return css::uno::Any();
138 // Job was done ... user configured deactivation of this job
140 if (bDeactivateJobIfDone
)
141 return ShellJob::impl_generateAnswer4Deactivation();
143 // There was no decision about deactivation of this job.
144 // So we have to return nothing here !
145 return css::uno::Any();
148 //-----------------------------------------------
149 css::uno::Any
ShellJob::impl_generateAnswer4Deactivation()
151 css::uno::Sequence
< css::beans::NamedValue
> aAnswer(1);
152 aAnswer
[0].Name
= JobConst::ANSWER_DEACTIVATE_JOB();
153 aAnswer
[0].Value
= css::uno::makeAny(sal_True
);
155 return css::uno::makeAny(aAnswer
);
158 //-----------------------------------------------
159 ::rtl::OUString
ShellJob::impl_substituteCommandVariables(const ::rtl::OUString
& sCommand
)
162 ReadGuard
aReadLock(m_aLock
);
163 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
169 css::uno::Reference
< css::util::XStringSubstitution
> xSubst ( xSMGR
->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES
), css::uno::UNO_QUERY_THROW
);
170 const ::sal_Bool bSubstRequired
= sal_True
;
171 const ::rtl::OUString sCompleteCommand
= xSubst
->substituteVariables(sCommand
, bSubstRequired
);
173 return sCompleteCommand
;
175 catch(const css::uno::Exception
&)
178 return ::rtl::OUString();
181 //-----------------------------------------------
182 ::sal_Bool
ShellJob::impl_execute(const ::rtl::OUString
& sCommand
,
183 const css::uno::Sequence
< ::rtl::OUString
>& lArguments
,
184 ::sal_Bool bCheckExitCode
)
186 ::rtl_uString
** pArgs
= NULL
;
187 const ::sal_Int32 nArgs
= lArguments
.getLength ();
188 oslProcessOption nOptions
= osl_Process_WAIT
;
189 oslProcess
hProcess(0);
192 pArgs
= reinterpret_cast< ::rtl_uString
** >(const_cast< ::rtl::OUString
* >(lArguments
.getConstArray()));
194 oslProcessError eError
= osl_executeProcess(sCommand
.pData
, pArgs
, nArgs
, nOptions
, NULL
, NULL
, NULL
, 0, &hProcess
);
196 // executable not found or couldnt be started
197 if (eError
!= osl_Process_E_None
)
200 ::sal_Bool bRet
= sal_True
;
203 // check its return codes ...
204 oslProcessInfo aInfo
;
205 aInfo
.Size
= sizeof (oslProcessInfo
);
206 eError
= osl_getProcessInfo(hProcess
, osl_Process_EXITCODE
, &aInfo
);
208 if (eError
!= osl_Process_E_None
)
211 bRet
= (aInfo
.Code
== 0);
213 osl_freeProcessHandle(hProcess
);
217 } // namespace framework