xref: /aoo41x/main/framework/source/jobs/shelljob.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_______________________________________________
32 // include own header
33 
34 #include <jobs/shelljob.hxx>
35 #include <jobs/jobconst.hxx>
36 #include <threadhelp/readguard.hxx>
37 #include <services.h>
38 
39 //_______________________________________________
40 // include others
41 
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>
47 
48 //_______________________________________________
49 // include interfaces
50 
51 #include <com/sun/star/system/XSystemShellExecute.hpp>
52 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
53 #include <com/sun/star/util/XStringSubstitution.hpp>
54 
55 //_______________________________________________
56 // namespace
57 
58 namespace framework{
59 
60 //_______________________________________________
61 // definitions
62 
63 /** adress job configuration inside argument set provided on method execute(). */
64 static const ::rtl::OUString PROP_JOBCONFIG = ::rtl::OUString::createFromAscii("JobConfig");
65 
66 /** adress job configuration property "Command". */
67 static const ::rtl::OUString PROP_COMMAND = ::rtl::OUString::createFromAscii("Command");
68 
69 /** adress job configuration property "Arguments". */
70 static const ::rtl::OUString PROP_ARGUMENTS = ::rtl::OUString::createFromAscii("Arguments");
71 
72 /** adress job configuration property "DeactivateJobIfDone". */
73 static const ::rtl::OUString PROP_DEACTIVATEJOBIFDONE = ::rtl::OUString::createFromAscii("DeactivateJobIfDone");
74 
75 /** adress job configuration property "CheckExitCode". */
76 static const ::rtl::OUString PROP_CHECKEXITCODE = ::rtl::OUString::createFromAscii("CheckExitCode");
77 
78 //-----------------------------------------------
79 
80 DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob                   ,
81                                  ::cppu::OWeakObject        ,
82                                  SERVICENAME_JOB            ,
83                                  IMPLEMENTATIONNAME_SHELLJOB)
84 
85 DEFINE_INIT_SERVICE(ShellJob,
86                     {
87                         /*  Attention
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!
91                         */
92                     }
93                    )
94 
95 //-----------------------------------------------
96 ShellJob::ShellJob(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
97     : ThreadHelpBase(     )
98     , m_xSMGR       (xSMGR)
99 {
100 }
101 
102 //-----------------------------------------------
103 ShellJob::~ShellJob()
104 {
105 }
106 
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         )
112 {
113 	::comphelper::SequenceAsHashMap lArgs  (lJobArguments);
114 	::comphelper::SequenceAsHashMap lOwnCfg(lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG, css::uno::Sequence< css::beans::NamedValue >()));
115 
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         );
120 
121     // replace all might existing place holder.
122     ::rtl::OUString sRealCommand = impl_substituteCommandVariables(sCommand);
123 
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();
129 
130     // do it
131     ::sal_Bool bDone = impl_execute(sRealCommand, lCommandArguments, bCheckExitCode);
132     if (! bDone)
133         return css::uno::Any();
134 
135     // Job was done ... user configured deactivation of this job
136     // in such case.
137     if (bDeactivateJobIfDone)
138         return ShellJob::impl_generateAnswer4Deactivation();
139 
140     // There was no decision about deactivation of this job.
141     // So we have to return nothing here !
142     return css::uno::Any();
143 }
144 
145 //-----------------------------------------------
146 css::uno::Any ShellJob::impl_generateAnswer4Deactivation()
147 {
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);
151 
152 	return css::uno::makeAny(aAnswer);
153 }
154 
155 //-----------------------------------------------
156 ::rtl::OUString ShellJob::impl_substituteCommandVariables(const ::rtl::OUString& sCommand)
157 {
158     // SYNCHRONIZED ->
159     ReadGuard aReadLock(m_aLock);
160     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
161     aReadLock.unlock();
162     // <- SYNCHRONIZED
163 
164 	try
165 	{
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);
169 
170         return sCompleteCommand;
171 	}
172 	catch(const css::uno::Exception&)
173 	{}
174 
175     return ::rtl::OUString();
176 }
177 
178 //-----------------------------------------------
179 ::sal_Bool ShellJob::impl_execute(const ::rtl::OUString&                       sCommand      ,
180                                   const css::uno::Sequence< ::rtl::OUString >& lArguments    ,
181                                         ::sal_Bool                             bCheckExitCode)
182 {
183           ::rtl_uString**  pArgs    = NULL;
184     const ::sal_Int32      nArgs    = lArguments.getLength ();
185           oslProcessOption nOptions = osl_Process_WAIT;
186           oslProcess       hProcess(0);
187 
188     if (nArgs > 0)
189         pArgs = reinterpret_cast< ::rtl_uString** >(const_cast< ::rtl::OUString* >(lArguments.getConstArray()));
190 
191     oslProcessError eError = osl_executeProcess(sCommand.pData, pArgs, nArgs, nOptions, NULL, NULL, NULL, 0, &hProcess);
192 
193     // executable not found or couldnt be started
194     if (eError != osl_Process_E_None)
195         return sal_False;
196 
197     ::sal_Bool bRet = sal_True;
198     if (bCheckExitCode)
199     {
200         // check its return codes ...
201         oslProcessInfo aInfo;
202         aInfo.Size = sizeof (oslProcessInfo);
203         eError = osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo);
204 
205         if (eError != osl_Process_E_None)
206             bRet = sal_False;
207         else
208             bRet = (aInfo.Code == 0);
209     }
210     osl_freeProcessHandle(hProcess);
211     return bRet;
212 }
213 
214 } // namespace framework
215