xref: /trunk/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