1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //_______________________________________________
34 #include <jobs/shelljob.hxx>
35 #include <jobs/jobconst.hxx>
36 #include <threadhelp/readguard.hxx>
39 //_______________________________________________
42 #include <osl/file.hxx>
43 #include <osl/process.h>
44 #include <vcl/svapp.hxx>
45 #include <rtl/ustrbuf.hxx>
46 #include <comphelper/sequenceashashmap.hxx>
48 //_______________________________________________
51 #include <com/sun/star/system/XSystemShellExecute.hpp>
52 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
53 #include <com/sun/star/util/XStringSubstitution.hpp>
55 //_______________________________________________
60 //_______________________________________________
63 /** adress job configuration inside argument set provided on method execute(). */
64 static const ::rtl::OUString PROP_JOBCONFIG
= ::rtl::OUString::createFromAscii("JobConfig");
66 /** adress job configuration property "Command". */
67 static const ::rtl::OUString PROP_COMMAND
= ::rtl::OUString::createFromAscii("Command");
69 /** adress job configuration property "Arguments". */
70 static const ::rtl::OUString PROP_ARGUMENTS
= ::rtl::OUString::createFromAscii("Arguments");
72 /** adress job configuration property "DeactivateJobIfDone". */
73 static const ::rtl::OUString PROP_DEACTIVATEJOBIFDONE
= ::rtl::OUString::createFromAscii("DeactivateJobIfDone");
75 /** adress job configuration property "CheckExitCode". */
76 static const ::rtl::OUString PROP_CHECKEXITCODE
= ::rtl::OUString::createFromAscii("CheckExitCode");
78 //-----------------------------------------------
80 DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob
,
83 IMPLEMENTATIONNAME_SHELLJOB
)
85 DEFINE_INIT_SERVICE(ShellJob
,
88 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
89 to create a new instance of this class by our own supported service factory.
90 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
95 //-----------------------------------------------
96 ShellJob::ShellJob(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
102 //-----------------------------------------------
103 ShellJob::~ShellJob()
107 //-----------------------------------------------
108 css::uno::Any SAL_CALL
ShellJob::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lJobArguments
)
109 throw(css::lang::IllegalArgumentException
,
110 css::uno::Exception
,
111 css::uno::RuntimeException
)
113 ::comphelper::SequenceAsHashMap
lArgs (lJobArguments
);
114 ::comphelper::SequenceAsHashMap
lOwnCfg(lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>()));
116 const ::rtl::OUString sCommand
= lOwnCfg
.getUnpackedValueOrDefault(PROP_COMMAND
, ::rtl::OUString());
117 const css::uno::Sequence
< ::rtl::OUString
> lCommandArguments
= lOwnCfg
.getUnpackedValueOrDefault(PROP_ARGUMENTS
, css::uno::Sequence
< ::rtl::OUString
>());
118 const ::sal_Bool bDeactivateJobIfDone
= lOwnCfg
.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE
, sal_True
);
119 const ::sal_Bool bCheckExitCode
= lOwnCfg
.getUnpackedValueOrDefault(PROP_CHECKEXITCODE
, sal_True
);
121 // replace all might existing place holder.
122 ::rtl::OUString sRealCommand
= impl_substituteCommandVariables(sCommand
);
124 // Command is required as minimum.
125 // If it does not exists ... we cant do our job.
126 // Deactivate such miss configured job silently .-)
127 if (sRealCommand
.getLength() < 1)
128 return ShellJob::impl_generateAnswer4Deactivation();
131 ::sal_Bool bDone
= impl_execute(sRealCommand
, lCommandArguments
, bCheckExitCode
);
133 return css::uno::Any();
135 // Job was done ... user configured deactivation of this job
137 if (bDeactivateJobIfDone
)
138 return ShellJob::impl_generateAnswer4Deactivation();
140 // There was no decision about deactivation of this job.
141 // So we have to return nothing here !
142 return css::uno::Any();
145 //-----------------------------------------------
146 css::uno::Any
ShellJob::impl_generateAnswer4Deactivation()
148 css::uno::Sequence
< css::beans::NamedValue
> aAnswer(1);
149 aAnswer
[0].Name
= JobConst::ANSWER_DEACTIVATE_JOB();
150 aAnswer
[0].Value
= css::uno::makeAny(sal_True
);
152 return css::uno::makeAny(aAnswer
);
155 //-----------------------------------------------
156 ::rtl::OUString
ShellJob::impl_substituteCommandVariables(const ::rtl::OUString
& sCommand
)
159 ReadGuard
aReadLock(m_aLock
);
160 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
166 css::uno::Reference
< css::util::XStringSubstitution
> xSubst ( xSMGR
->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES
), css::uno::UNO_QUERY_THROW
);
167 const ::sal_Bool bSubstRequired
= sal_True
;
168 const ::rtl::OUString sCompleteCommand
= xSubst
->substituteVariables(sCommand
, bSubstRequired
);
170 return sCompleteCommand
;
172 catch(const css::uno::Exception
&)
175 return ::rtl::OUString();
178 //-----------------------------------------------
179 ::sal_Bool
ShellJob::impl_execute(const ::rtl::OUString
& sCommand
,
180 const css::uno::Sequence
< ::rtl::OUString
>& lArguments
,
181 ::sal_Bool bCheckExitCode
)
183 ::rtl_uString
** pArgs
= NULL
;
184 const ::sal_Int32 nArgs
= lArguments
.getLength ();
185 oslProcessOption nOptions
= osl_Process_WAIT
;
186 oslProcess
hProcess(0);
189 pArgs
= reinterpret_cast< ::rtl_uString
** >(const_cast< ::rtl::OUString
* >(lArguments
.getConstArray()));
191 oslProcessError eError
= osl_executeProcess(sCommand
.pData
, pArgs
, nArgs
, nOptions
, NULL
, NULL
, NULL
, 0, &hProcess
);
193 // executable not found or couldnt be started
194 if (eError
!= osl_Process_E_None
)
197 ::sal_Bool bRet
= sal_True
;
200 // check its return codes ...
201 oslProcessInfo aInfo
;
202 aInfo
.Size
= sizeof (oslProcessInfo
);
203 eError
= osl_getProcessInfo(hProcess
, osl_Process_EXITCODE
, &aInfo
);
205 if (eError
!= osl_Process_E_None
)
208 bRet
= (aInfo
.Code
== 0);
210 osl_freeProcessHandle(hProcess
);
214 } // namespace framework