1*ef39d40dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ef39d40dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ef39d40dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ef39d40dSAndrew Rist  * distributed with this work for additional information
6*ef39d40dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ef39d40dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ef39d40dSAndrew Rist  * "License"); you may not use this file except in compliance
9*ef39d40dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ef39d40dSAndrew Rist  *
11*ef39d40dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ef39d40dSAndrew Rist  *
13*ef39d40dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ef39d40dSAndrew Rist  * software distributed under the License is distributed on an
15*ef39d40dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ef39d40dSAndrew Rist  * KIND, either express or implied.  See the License for the
17*ef39d40dSAndrew Rist  * specific language governing permissions and limitations
18*ef39d40dSAndrew Rist  * under the License.
19*ef39d40dSAndrew Rist  *
20*ef39d40dSAndrew Rist  *************************************************************/
21*ef39d40dSAndrew Rist 
22*ef39d40dSAndrew Rist 
23cdf0e10cSrcweir package helper;
24cdf0e10cSrcweir 
25cdf0e10cSrcweir //import com.sun.star.bridge.UnoUrlResolver;
26cdf0e10cSrcweir import com.sun.star.beans.XFastPropertySet;
27cdf0e10cSrcweir import com.sun.star.bridge.XUnoUrlResolver;
28cdf0e10cSrcweir import com.sun.star.container.XEnumeration;
29cdf0e10cSrcweir import com.sun.star.container.XEnumerationAccess;
30cdf0e10cSrcweir import com.sun.star.frame.XDesktop;
31cdf0e10cSrcweir import com.sun.star.lang.XMultiComponentFactory;
32cdf0e10cSrcweir import com.sun.star.lang.XMultiServiceFactory;
33cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
34cdf0e10cSrcweir import com.sun.star.uno.XComponentContext;
35cdf0e10cSrcweir import com.sun.star.util.XCloseable;
36cdf0e10cSrcweir import com.sun.star.util.XStringSubstitution;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir import java.io.File;
39cdf0e10cSrcweir import java.io.PrintWriter;
40cdf0e10cSrcweir import java.util.StringTokenizer;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir import lib.TestParameters;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir import share.DescEntry;
45cdf0e10cSrcweir import share.LogWriter;
46cdf0e10cSrcweir 
47cdf0e10cSrcweir import util.DynamicClassLoader;
48cdf0e10cSrcweir import util.PropertyName;
49cdf0e10cSrcweir import util.utils;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir /**
52cdf0e10cSrcweir  * This class will connect the office and start it if possible
53cdf0e10cSrcweir  *
54cdf0e10cSrcweir  */
55cdf0e10cSrcweir public class OfficeProvider implements AppProvider
56cdf0e10cSrcweir {
57cdf0e10cSrcweir 
58cdf0e10cSrcweir     private static boolean debug = false;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir     /**
61cdf0e10cSrcweir      * copy the user layer to a safe place, usualy to $TMP/user_backup$USER
62cdf0e10cSrcweir      * @param param
63cdf0e10cSrcweir      * @param msf
64cdf0e10cSrcweir      */
65cdf0e10cSrcweir     public void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
66cdf0e10cSrcweir     {
67cdf0e10cSrcweir         try
68cdf0e10cSrcweir         {
69cdf0e10cSrcweir             final XStringSubstitution sts = createStringSubstitution(msf);
70cdf0e10cSrcweir             debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
71cdf0e10cSrcweir 
72cdf0e10cSrcweir             String userLayer = sts.getSubstituteVariableValue("$(user)");
73cdf0e10cSrcweir             userLayer = getDirSys(userLayer);
74cdf0e10cSrcweir             param.put("userLayer", userLayer);
75cdf0e10cSrcweir 
76cdf0e10cSrcweir             final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
77cdf0e10cSrcweir                     "user_backup" +
78cdf0e10cSrcweir                     System.getProperty("user.name");
79cdf0e10cSrcweir             param.put("copyLayer", copyLayer);
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 
82cdf0e10cSrcweir             dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
83cdf0e10cSrcweir             // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
84cdf0e10cSrcweir             OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
85cdf0e10cSrcweir             owp.start();
86cdf0e10cSrcweir 
87cdf0e10cSrcweir             deleteFilesAndDirector (new File(copyLayer));
88cdf0e10cSrcweir             FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
89cdf0e10cSrcweir                     {
90cdf0e10cSrcweir                         "temp"
91cdf0e10cSrcweir                     });
92cdf0e10cSrcweir 
93cdf0e10cSrcweir             owp.finish();
94cdf0e10cSrcweir 
95cdf0e10cSrcweir         }
96cdf0e10cSrcweir         catch (com.sun.star.container.NoSuchElementException e)
97cdf0e10cSrcweir         {
98cdf0e10cSrcweir             System.out.println("User Variable '$(user)' not defined.");
99cdf0e10cSrcweir         }
100cdf0e10cSrcweir         catch (java.io.IOException e)
101cdf0e10cSrcweir         {
102cdf0e10cSrcweir             System.out.println("Couldn't backup user layer");
103cdf0e10cSrcweir             e.printStackTrace();
104cdf0e10cSrcweir         }
105cdf0e10cSrcweir     }
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     /**
108cdf0e10cSrcweir      * Dispose the office.
109cdf0e10cSrcweir      * This method can only be used, if the office was connected in the first
110cdf0e10cSrcweir      * place: getManager() was called first.
111cdf0e10cSrcweir      * @param param
112cdf0e10cSrcweir      * @return return true if desktop is terminates, else false
113cdf0e10cSrcweir      */
114cdf0e10cSrcweir     public boolean disposeManager(lib.TestParameters param)
115cdf0e10cSrcweir     {
116cdf0e10cSrcweir 
117cdf0e10cSrcweir         XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
118cdf0e10cSrcweir 
119cdf0e10cSrcweir         if (msf == null)
120cdf0e10cSrcweir         {
121cdf0e10cSrcweir             return true;
122cdf0e10cSrcweir         }
123cdf0e10cSrcweir         else
124cdf0e10cSrcweir         {
125cdf0e10cSrcweir             XDesktop desk = null;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir             try
128cdf0e10cSrcweir             {
129cdf0e10cSrcweir                 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
130cdf0e10cSrcweir             }
131cdf0e10cSrcweir             catch (com.sun.star.uno.Exception ue)
132cdf0e10cSrcweir             {
133cdf0e10cSrcweir                 return false;
134cdf0e10cSrcweir             }
135cdf0e10cSrcweir 
136cdf0e10cSrcweir             msf = null;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir             if (desk != null)
139cdf0e10cSrcweir             {
140cdf0e10cSrcweir                 desk.terminate();
141cdf0e10cSrcweir 
142cdf0e10cSrcweir                 return true;
143cdf0e10cSrcweir             }
144cdf0e10cSrcweir             else
145cdf0e10cSrcweir             {
146cdf0e10cSrcweir                 return false;
147cdf0e10cSrcweir             }
148cdf0e10cSrcweir         }
149cdf0e10cSrcweir     }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir     /**
152cdf0e10cSrcweir      * Method to get the ServiceManager of an Office
153cdf0e10cSrcweir      * @param param
154cdf0e10cSrcweir      * @return
155cdf0e10cSrcweir      */
156cdf0e10cSrcweir     public Object getManager(lib.TestParameters param)
157cdf0e10cSrcweir     {
158cdf0e10cSrcweir         String errorMessage = null;
159cdf0e10cSrcweir         boolean bAppExecutionHasWarning = false;
160cdf0e10cSrcweir         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         String additionalArgs = (String) param.get(
163cdf0e10cSrcweir                 "AdditionalConnectionArguments");
164cdf0e10cSrcweir 
165cdf0e10cSrcweir         if (additionalArgs == null)
166cdf0e10cSrcweir         {
167cdf0e10cSrcweir             additionalArgs = ";";
168cdf0e10cSrcweir         }
169cdf0e10cSrcweir         else
170cdf0e10cSrcweir         {
171cdf0e10cSrcweir             additionalArgs = "," + additionalArgs + ";";
172cdf0e10cSrcweir         }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
175cdf0e10cSrcweir                 additionalArgs + "StarOffice.ServiceManager";
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         System.out.println("Connecting the Office with " + cncstr);
178cdf0e10cSrcweir 
179cdf0e10cSrcweir         XMultiServiceFactory msf = connectOffice(cncstr);
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         // if the office is running and the office crashes while testing it could
182cdf0e10cSrcweir         // be usesfull to restart the office if possible and continuing the tests.
183cdf0e10cSrcweir         // Example: The UNO-API-Tests in the projects will be executed by calling
184cdf0e10cSrcweir         // 'damke'. This connects to an existing office. If the office crashes
185cdf0e10cSrcweir         // it is usefull to restart the office and continuing the tests.
186cdf0e10cSrcweir         if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
187cdf0e10cSrcweir         {
188cdf0e10cSrcweir             makeAppExecCommand(msf, param);
189cdf0e10cSrcweir         }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir         if (msf == null)
192cdf0e10cSrcweir         {
193cdf0e10cSrcweir             String exc = "";
194cdf0e10cSrcweir             Exception exConnectFailed = null;
195cdf0e10cSrcweir             boolean isExecutable = false;
196cdf0e10cSrcweir             boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
197cdf0e10cSrcweir             isAppKnown &= !((String) param.get("AppExecutionCommand")).equals("");
198cdf0e10cSrcweir 
199cdf0e10cSrcweir             if (isAppKnown)
200cdf0e10cSrcweir             {
201cdf0e10cSrcweir                 dbg("Local Connection trying to start the Office");
202cdf0e10cSrcweir 
203cdf0e10cSrcweir                 //ensure that a pending officewatcher gets finished before a new
204cdf0e10cSrcweir                 //office is started
205cdf0e10cSrcweir                 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
206cdf0e10cSrcweir 
207cdf0e10cSrcweir                 if (ow_old != null)
208cdf0e10cSrcweir                 {
209cdf0e10cSrcweir                     ow_old.finish = true;
210cdf0e10cSrcweir                 }
211cdf0e10cSrcweir 
212cdf0e10cSrcweir                 final String cmd = (String) param.get("AppExecutionCommand");
213cdf0e10cSrcweir                 dbg("AppExecutionCommand: " + cmd);
214cdf0e10cSrcweir                 // validate the AppExecutionCommand, but try it out anyway.
215cdf0e10cSrcweir                 // keep the error message for later.
216cdf0e10cSrcweir                 errorMessage =
217cdf0e10cSrcweir                         util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
218cdf0e10cSrcweir                 if (errorMessage.startsWith("Error"))
219cdf0e10cSrcweir                 {
220cdf0e10cSrcweir                     System.out.println(errorMessage);
221cdf0e10cSrcweir                     return null;
222cdf0e10cSrcweir                 }
223cdf0e10cSrcweir                 bAppExecutionHasWarning = !errorMessage.equals("OK");
224cdf0e10cSrcweir 
225cdf0e10cSrcweir                 final DynamicClassLoader dcl = new DynamicClassLoader();
226cdf0e10cSrcweir                 final LogWriter log = (LogWriter) dcl.getInstance(
227cdf0e10cSrcweir                         (String) param.get("LogWriter"));
228cdf0e10cSrcweir 
229cdf0e10cSrcweir                 //create empty entry
230cdf0e10cSrcweir                 final DescEntry Entry = new DescEntry();
231cdf0e10cSrcweir                 Entry.entryName = "office";
232cdf0e10cSrcweir                 Entry.longName = "office";
233cdf0e10cSrcweir                 Entry.EntryType = "placebo";
234cdf0e10cSrcweir                 Entry.isOptional = false;
235cdf0e10cSrcweir                 Entry.isToTest = false;
236cdf0e10cSrcweir                 Entry.SubEntryCount = 0;
237cdf0e10cSrcweir                 Entry.hasErrorMsg = false;
238cdf0e10cSrcweir                 Entry.State = "non possible";
239cdf0e10cSrcweir                 Entry.UserDefinedParams = param;
240cdf0e10cSrcweir 
241cdf0e10cSrcweir                 log.initialize(Entry, debug);
242cdf0e10cSrcweir 
243cdf0e10cSrcweir                 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
244cdf0e10cSrcweir                 isExecutable = ph.executeAsynchronously();
245cdf0e10cSrcweir 
246cdf0e10cSrcweir                 if (isExecutable)
247cdf0e10cSrcweir                 {
248cdf0e10cSrcweir                     param.put("AppProvider", ph);
249cdf0e10cSrcweir                     final OfficeWatcher ow = new OfficeWatcher(param);
250cdf0e10cSrcweir                     param.put("Watcher", ow);
251cdf0e10cSrcweir                     ow.start();
252cdf0e10cSrcweir                     ow.ping();
253cdf0e10cSrcweir                 }
254cdf0e10cSrcweir 
255cdf0e10cSrcweir                 int k = 0;
256cdf0e10cSrcweir 
257cdf0e10cSrcweir                 // wait up to 21 seconds to get an office connection
258cdf0e10cSrcweir                 while ((k < 42) && (msf == null))
259cdf0e10cSrcweir                 {
260cdf0e10cSrcweir                     try
261cdf0e10cSrcweir                     {
262cdf0e10cSrcweir                         msf = connect(cncstr);
263cdf0e10cSrcweir                     }
264cdf0e10cSrcweir                     catch (com.sun.star.uno.Exception ue)
265cdf0e10cSrcweir                     {
266cdf0e10cSrcweir                         exConnectFailed = ue;
267cdf0e10cSrcweir                         exc = ue.getMessage();
268cdf0e10cSrcweir                     }
269cdf0e10cSrcweir                     catch (java.lang.Exception je)
270cdf0e10cSrcweir                     {
271cdf0e10cSrcweir                         exConnectFailed = je;
272cdf0e10cSrcweir                         exc = je.getMessage();
273cdf0e10cSrcweir                     }
274cdf0e10cSrcweir                     if (msf == null)
275cdf0e10cSrcweir                     {
276cdf0e10cSrcweir                         try
277cdf0e10cSrcweir                         {
278cdf0e10cSrcweir                             Thread.sleep(k * 500);
279cdf0e10cSrcweir                         }
280cdf0e10cSrcweir                         catch (InterruptedException ex)
281cdf0e10cSrcweir                         {
282cdf0e10cSrcweir                         }
283cdf0e10cSrcweir                     }
284cdf0e10cSrcweir                     k++;
285cdf0e10cSrcweir                 }
286cdf0e10cSrcweir 
287cdf0e10cSrcweir                 if (msf == null)
288cdf0e10cSrcweir                 {
289cdf0e10cSrcweir                     System.out.println("Exception while connecting.\n" + exConnectFailed);
290cdf0e10cSrcweir                     if (exc != null)
291cdf0e10cSrcweir                     {
292cdf0e10cSrcweir                         System.out.println(exc);
293cdf0e10cSrcweir                     }
294cdf0e10cSrcweir                     if (bAppExecutionHasWarning)
295cdf0e10cSrcweir                     {
296cdf0e10cSrcweir                         System.out.println(errorMessage);
297cdf0e10cSrcweir                     }
298cdf0e10cSrcweir                 }
299cdf0e10cSrcweir                 else if (isExecutable)
300cdf0e10cSrcweir                 {
301cdf0e10cSrcweir                     if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
302cdf0e10cSrcweir                     {
303cdf0e10cSrcweir                         backupUserLayer(param, msf);
304cdf0e10cSrcweir                     }
305cdf0e10cSrcweir                 }
306cdf0e10cSrcweir             }
307cdf0e10cSrcweir             else
308cdf0e10cSrcweir             {
309cdf0e10cSrcweir                 System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
310cdf0e10cSrcweir                         concat("\nsoffice -accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
311cdf0e10cSrcweir                 if (bAppExecutionHasWarning)
312cdf0e10cSrcweir                 {
313cdf0e10cSrcweir                     System.out.println(errorMessage);
314cdf0e10cSrcweir                 }
315cdf0e10cSrcweir             }
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir         return msf;
319cdf0e10cSrcweir     }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     /**
322cdf0e10cSrcweir      * Connect an Office
323cdf0e10cSrcweir      * @param connectStr
324cdf0e10cSrcweir      * @return
325cdf0e10cSrcweir      * @throws com.sun.star.uno.Exception
326cdf0e10cSrcweir      * @throws com.sun.star.uno.RuntimeException
327cdf0e10cSrcweir      * @throws com.sun.star.connection.NoConnectException
328cdf0e10cSrcweir      * @throws Exception
329cdf0e10cSrcweir      */
330cdf0e10cSrcweir     protected static XMultiServiceFactory connect(String connectStr)
331cdf0e10cSrcweir             throws com.sun.star.uno.Exception,
332cdf0e10cSrcweir             com.sun.star.uno.RuntimeException,
333cdf0e10cSrcweir             com.sun.star.connection.NoConnectException,
334cdf0e10cSrcweir             Exception
335cdf0e10cSrcweir     {
336cdf0e10cSrcweir 
337cdf0e10cSrcweir         // Get component context
338cdf0e10cSrcweir         final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
339cdf0e10cSrcweir 
340cdf0e10cSrcweir         // initial serviceManager
341cdf0e10cSrcweir         final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
342cdf0e10cSrcweir 
343cdf0e10cSrcweir         // create a connector, so that it can contact the office
344cdf0e10cSrcweir //        XUnoUrlResolver urlResolver = UnoUrlResolver.create(xcomponentcontext);
345cdf0e10cSrcweir         final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
346cdf0e10cSrcweir         final XUnoUrlResolver urlResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, xUrlResolver);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir         final Object rInitialObject = urlResolver.resolve(connectStr);
349cdf0e10cSrcweir 
350cdf0e10cSrcweir         XMultiServiceFactory xMSF = null;
351cdf0e10cSrcweir 
352cdf0e10cSrcweir         if (rInitialObject != null)
353cdf0e10cSrcweir         {
354cdf0e10cSrcweir             // debug = true;
355cdf0e10cSrcweir             dbg("resolved url");
356cdf0e10cSrcweir 
357cdf0e10cSrcweir             xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
358cdf0e10cSrcweir         }
359cdf0e10cSrcweir 
360cdf0e10cSrcweir         return xMSF;
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     /**
364cdf0e10cSrcweir      * Close an office.
365cdf0e10cSrcweir      * @param param The test parameters.
366cdf0e10cSrcweir      * @param closeIfPossible If true, close even if
367cdf0e10cSrcweir      * it was running before the test
368cdf0e10cSrcweir      */
369cdf0e10cSrcweir     public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
370cdf0e10cSrcweir     {
371cdf0e10cSrcweir 
372cdf0e10cSrcweir         XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
373cdf0e10cSrcweir         final boolean alreadyConnected = (msf != null);
374cdf0e10cSrcweir         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
375cdf0e10cSrcweir 
376cdf0e10cSrcweir         if (alreadyConnected)
377cdf0e10cSrcweir         {
378cdf0e10cSrcweir             dbg("try to get ProcessHandler");
379cdf0e10cSrcweir 
380cdf0e10cSrcweir             final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
381cdf0e10cSrcweir 
382cdf0e10cSrcweir             if (ph != null)
383cdf0e10cSrcweir             {
384cdf0e10cSrcweir                 dbg("ProcessHandler != null");
385cdf0e10cSrcweir 
386cdf0e10cSrcweir                 disposeOffice(msf, param);
387cdf0e10cSrcweir 
388cdf0e10cSrcweir                 // dispose watcher in case it's still running.
389cdf0e10cSrcweir                 dbg("try to get OfficeWatcher");
390cdf0e10cSrcweir 
391cdf0e10cSrcweir                 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
392cdf0e10cSrcweir 
393cdf0e10cSrcweir                 if ((ow != null) && ow.isAlive())
394cdf0e10cSrcweir                 {
395cdf0e10cSrcweir                     dbg("OfficeWatcher will be finished");
396cdf0e10cSrcweir                     ow.finish = true;
397cdf0e10cSrcweir                 }
398cdf0e10cSrcweir                 else
399cdf0e10cSrcweir                 {
400cdf0e10cSrcweir                     dbg("OfficeWatcher seems to be finished");
401cdf0e10cSrcweir                 }
402cdf0e10cSrcweir 
403cdf0e10cSrcweir                 return true;
404cdf0e10cSrcweir             }
405cdf0e10cSrcweir             else
406cdf0e10cSrcweir             {
407cdf0e10cSrcweir                 if (closeIfPossible)
408cdf0e10cSrcweir                 {
409cdf0e10cSrcweir                     return disposeOffice(msf, param);
410cdf0e10cSrcweir                 }
411cdf0e10cSrcweir             }
412cdf0e10cSrcweir         }
413cdf0e10cSrcweir         else
414cdf0e10cSrcweir         {
415cdf0e10cSrcweir             final String cncstr = "uno:" + param.get("ConnectionString") +
416cdf0e10cSrcweir                     ";urp;StarOffice.ServiceManager";
417cdf0e10cSrcweir             dbg("try to connect office");
418cdf0e10cSrcweir             msf = connectOffice(cncstr);
419cdf0e10cSrcweir 
420cdf0e10cSrcweir             if (closeIfPossible)
421cdf0e10cSrcweir             {
422cdf0e10cSrcweir                 return disposeOffice(msf, param);
423cdf0e10cSrcweir             }
424cdf0e10cSrcweir         }
425cdf0e10cSrcweir         dbg("closeExistingOffice finished");
426cdf0e10cSrcweir         return true;
427cdf0e10cSrcweir     }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir     private XMultiServiceFactory connectOffice(String cncstr)
430cdf0e10cSrcweir     {
431cdf0e10cSrcweir         XMultiServiceFactory msf = null;
432cdf0e10cSrcweir         String exc = "";
433cdf0e10cSrcweir         // debug = true;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir         dbg("trying to connect to " + cncstr);
436cdf0e10cSrcweir 
437cdf0e10cSrcweir         try
438cdf0e10cSrcweir         {
439cdf0e10cSrcweir             msf = connect(cncstr);
440cdf0e10cSrcweir         }
441cdf0e10cSrcweir         catch (com.sun.star.uno.Exception ue)
442cdf0e10cSrcweir         {
443cdf0e10cSrcweir             exc = ue.getMessage();
444cdf0e10cSrcweir         }
445cdf0e10cSrcweir         catch (java.lang.Exception je)
446cdf0e10cSrcweir         {
447cdf0e10cSrcweir             exc = je.getMessage();
448cdf0e10cSrcweir         }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir         if (debug && exc != null && exc.length() != 0)
451cdf0e10cSrcweir         {
452cdf0e10cSrcweir             if (exc == null)
453cdf0e10cSrcweir             {
454cdf0e10cSrcweir                 exc = "";
455cdf0e10cSrcweir             }
456cdf0e10cSrcweir             dbg("Could not connect an Office. " + exc);
457cdf0e10cSrcweir         }
458cdf0e10cSrcweir 
459cdf0e10cSrcweir         return msf;
460cdf0e10cSrcweir     }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir     private synchronized boolean disposeOffice(XMultiServiceFactory msf,
463cdf0e10cSrcweir             TestParameters param)
464cdf0e10cSrcweir     {
465cdf0e10cSrcweir         XDesktop desk = null;
466cdf0e10cSrcweir 
467cdf0e10cSrcweir         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
468cdf0e10cSrcweir 
469cdf0e10cSrcweir         boolean result = true;
470cdf0e10cSrcweir 
471cdf0e10cSrcweir         if (msf != null)
472cdf0e10cSrcweir         {
473cdf0e10cSrcweir 
474cdf0e10cSrcweir             // disable QuickStarter
475cdf0e10cSrcweir             try
476cdf0e10cSrcweir             {
477cdf0e10cSrcweir                 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
478cdf0e10cSrcweir                 XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
479cdf0e10cSrcweir                 fps.setFastPropertyValue(0, false);
480cdf0e10cSrcweir             }
481cdf0e10cSrcweir             catch (com.sun.star.uno.Exception ex)
482cdf0e10cSrcweir             {
483cdf0e10cSrcweir                 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
484cdf0e10cSrcweir             }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir             try
487cdf0e10cSrcweir             {
488cdf0e10cSrcweir                 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
489cdf0e10cSrcweir                 msf = null;
490cdf0e10cSrcweir 
491cdf0e10cSrcweir                 if (desk != null)
492cdf0e10cSrcweir                 {
493cdf0e10cSrcweir                     final boolean allClosed = closeAllWindows(desk);
494cdf0e10cSrcweir 
495cdf0e10cSrcweir                     if (!allClosed)
496cdf0e10cSrcweir                     {
497cdf0e10cSrcweir                         dbg("Couldn't close all office windows!");
498cdf0e10cSrcweir                     }
499cdf0e10cSrcweir 
500cdf0e10cSrcweir                     dbg("Trying to terminate the desktop");
501cdf0e10cSrcweir 
502cdf0e10cSrcweir                     desk.terminate();
503cdf0e10cSrcweir                     dbg("Desktop terminated");
504cdf0e10cSrcweir 
505cdf0e10cSrcweir                     try
506cdf0e10cSrcweir                     {
507cdf0e10cSrcweir                         final int closeTime = param.getInt(util.PropertyName.OFFICE_CLOSE_TIME_OUT);
508cdf0e10cSrcweir                         dbg("the Office has " + closeTime / 1000 + " seconds for closing...");
509cdf0e10cSrcweir                         Thread.sleep(closeTime);
510cdf0e10cSrcweir                     }
511cdf0e10cSrcweir                     catch (java.lang.InterruptedException e)
512cdf0e10cSrcweir                     {
513cdf0e10cSrcweir                     }
514cdf0e10cSrcweir                 }
515cdf0e10cSrcweir             }
516cdf0e10cSrcweir             catch (com.sun.star.uno.Exception ue)
517cdf0e10cSrcweir             {
518cdf0e10cSrcweir                 result = false;
519cdf0e10cSrcweir             }
520cdf0e10cSrcweir             catch (com.sun.star.lang.DisposedException ue)
521cdf0e10cSrcweir             {
522cdf0e10cSrcweir                 result = false;
523cdf0e10cSrcweir             }
524cdf0e10cSrcweir         }
525cdf0e10cSrcweir 
526cdf0e10cSrcweir         final String AppKillCommand = (String) param.get(util.PropertyName.APP_KILL_COMMAND);
527cdf0e10cSrcweir         if (AppKillCommand != null)
528cdf0e10cSrcweir         {
529cdf0e10cSrcweir             String sAppKillCommand = StringHelper.removeSurroundQuoteIfExists(AppKillCommand);
530cdf0e10cSrcweir             final StringTokenizer aKillCommandToken = new StringTokenizer(sAppKillCommand, ";");
531cdf0e10cSrcweir             while (aKillCommandToken.hasMoreTokens())
532cdf0e10cSrcweir             {
533cdf0e10cSrcweir                 final String sKillCommand = aKillCommandToken.nextToken();
534cdf0e10cSrcweir                 dbg("User defined an application to destroy the started process. Trying to execute: " + sKillCommand);
535cdf0e10cSrcweir 
536cdf0e10cSrcweir                 final ProcessHandler pHdl = new ProcessHandler(sKillCommand, 1000); // 3000 seems to be too long
537cdf0e10cSrcweir                 pHdl.runCommand();
538cdf0e10cSrcweir 
539cdf0e10cSrcweir                 pHdl.kill();
540cdf0e10cSrcweir             }
541cdf0e10cSrcweir         }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir         final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
544cdf0e10cSrcweir 
545cdf0e10cSrcweir         if (ph != null)
546cdf0e10cSrcweir         {
547cdf0e10cSrcweir             // dispose watcher in case it's still running.
548cdf0e10cSrcweir             final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
549cdf0e10cSrcweir 
550cdf0e10cSrcweir             if ((ow != null) && ow.isAlive())
551cdf0e10cSrcweir             {
552cdf0e10cSrcweir                 ow.finish = true;
553cdf0e10cSrcweir             }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir             ph.kill();
556cdf0e10cSrcweir         }
557cdf0e10cSrcweir 
558cdf0e10cSrcweir         param.remove("AppProvider");
559cdf0e10cSrcweir         param.remove("ServiceFactory");
560cdf0e10cSrcweir 
561cdf0e10cSrcweir         if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
562cdf0e10cSrcweir         {
563cdf0e10cSrcweir             //copy user_backup into user layer
564cdf0e10cSrcweir             try
565cdf0e10cSrcweir             {
566cdf0e10cSrcweir                 final String userLayer = (String) param.get("userLayer");
567cdf0e10cSrcweir                 final String copyLayer = (String) param.get("copyLayer");
568cdf0e10cSrcweir                 if (userLayer != null && copyLayer != null)
569cdf0e10cSrcweir                 {
570cdf0e10cSrcweir                     deleteFilesAndDirector(new File(userLayer));
571cdf0e10cSrcweir                     final File copyFile = new File(copyLayer);
572cdf0e10cSrcweir                     dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
573cdf0e10cSrcweir                     FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
574cdf0e10cSrcweir                             {
575cdf0e10cSrcweir                                 "temp"
576cdf0e10cSrcweir                             });
577cdf0e10cSrcweir                     dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
578cdf0e10cSrcweir 
579cdf0e10cSrcweir                 // remove all user_backup folder in temp dir
580cdf0e10cSrcweir                 // this is for the case the runner was killed and some old backup folder still stay in temp dir
581cdf0e10cSrcweir 
582cdf0e10cSrcweir 
583cdf0e10cSrcweir                 }
584cdf0e10cSrcweir                 else
585cdf0e10cSrcweir                 {
586cdf0e10cSrcweir                     System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
587cdf0e10cSrcweir                 }
588cdf0e10cSrcweir             }
589cdf0e10cSrcweir             catch (java.io.IOException e)
590cdf0e10cSrcweir             {
591cdf0e10cSrcweir                 dbg("Couldn't recover from backup\n" + e.getMessage());
592cdf0e10cSrcweir             }
593cdf0e10cSrcweir         }
594cdf0e10cSrcweir         return result;
595cdf0e10cSrcweir     }
596cdf0e10cSrcweir 
597cdf0e10cSrcweir     protected boolean closeAllWindows(XDesktop desk)
598cdf0e10cSrcweir     {
599cdf0e10cSrcweir         final XEnumerationAccess compEnumAccess = desk.getComponents();
600cdf0e10cSrcweir         final XEnumeration compEnum = compEnumAccess.createEnumeration();
601cdf0e10cSrcweir         boolean res = true;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir         try
604cdf0e10cSrcweir         {
605cdf0e10cSrcweir             while (compEnum.hasMoreElements())
606cdf0e10cSrcweir             {
607cdf0e10cSrcweir                 final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
608cdf0e10cSrcweir 
609cdf0e10cSrcweir                 if (closer != null)
610cdf0e10cSrcweir                 {
611cdf0e10cSrcweir                     closer.close(true);
612cdf0e10cSrcweir                 }
613cdf0e10cSrcweir             }
614cdf0e10cSrcweir         }
615cdf0e10cSrcweir         catch (com.sun.star.util.CloseVetoException cve)
616cdf0e10cSrcweir         {
617cdf0e10cSrcweir             res = false;
618cdf0e10cSrcweir         }
619cdf0e10cSrcweir         catch (com.sun.star.container.NoSuchElementException nsee)
620cdf0e10cSrcweir         {
621cdf0e10cSrcweir             res = false;
622cdf0e10cSrcweir         }
623cdf0e10cSrcweir         catch (com.sun.star.lang.WrappedTargetException wte)
624cdf0e10cSrcweir         {
625cdf0e10cSrcweir             res = false;
626cdf0e10cSrcweir         }
627cdf0e10cSrcweir 
628cdf0e10cSrcweir         return res;
629cdf0e10cSrcweir     }
630cdf0e10cSrcweir 
631cdf0e10cSrcweir     public static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
632cdf0e10cSrcweir     {
633cdf0e10cSrcweir         Object xPathSubst = null;
634cdf0e10cSrcweir 
635cdf0e10cSrcweir         try
636cdf0e10cSrcweir         {
637cdf0e10cSrcweir             xPathSubst = xMSF.createInstance(
638cdf0e10cSrcweir                     "com.sun.star.util.PathSubstitution");
639cdf0e10cSrcweir         }
640cdf0e10cSrcweir         catch (com.sun.star.uno.Exception e)
641cdf0e10cSrcweir         {
642cdf0e10cSrcweir             e.printStackTrace();
643cdf0e10cSrcweir         }
644cdf0e10cSrcweir 
645cdf0e10cSrcweir         if (xPathSubst != null)
646cdf0e10cSrcweir         {
647cdf0e10cSrcweir             return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
648cdf0e10cSrcweir         }
649cdf0e10cSrcweir         else
650cdf0e10cSrcweir         {
651cdf0e10cSrcweir             return null;
652cdf0e10cSrcweir         }
653cdf0e10cSrcweir     }
654cdf0e10cSrcweir 
655cdf0e10cSrcweir     /**
656cdf0e10cSrcweir      * converts directory without 'file:///' prefix.
657cdf0e10cSrcweir      * and System dependend file separator
658cdf0e10cSrcweir      * @param dir
659cdf0e10cSrcweir      * @return
660cdf0e10cSrcweir      */
661cdf0e10cSrcweir     public static String getDirSys(String dir)
662cdf0e10cSrcweir     {
663cdf0e10cSrcweir         String sysDir = "";
664cdf0e10cSrcweir 
665cdf0e10cSrcweir         final int idx = dir.indexOf("file://");
666cdf0e10cSrcweir 
667cdf0e10cSrcweir         final int idx2 = dir.indexOf("file:///");
668cdf0e10cSrcweir 
669cdf0e10cSrcweir         // remove leading 'file://'
670cdf0e10cSrcweir         if (idx < 0)
671cdf0e10cSrcweir         {
672cdf0e10cSrcweir             sysDir = dir;
673cdf0e10cSrcweir         }
674cdf0e10cSrcweir         else
675cdf0e10cSrcweir         {
676cdf0e10cSrcweir             sysDir = dir.substring("file://".length());
677cdf0e10cSrcweir         }
678cdf0e10cSrcweir 
679cdf0e10cSrcweir         sysDir = utils.replaceAll13(sysDir, "%20", " ");
680cdf0e10cSrcweir 
681cdf0e10cSrcweir         // append '/' if not there (e.g. linux)
682cdf0e10cSrcweir         if (sysDir.charAt(sysDir.length() - 1) != '/')
683cdf0e10cSrcweir         {
684cdf0e10cSrcweir             sysDir += "/";
685cdf0e10cSrcweir         }
686cdf0e10cSrcweir 
687cdf0e10cSrcweir         // remove leading '/' and replace others with '\' on windows machines
688cdf0e10cSrcweir         final String sep = System.getProperty("file.separator");
689cdf0e10cSrcweir 
690cdf0e10cSrcweir         if (sep.equalsIgnoreCase("\\"))
691cdf0e10cSrcweir         {
692cdf0e10cSrcweir             if (!(idx2 < 0))
693cdf0e10cSrcweir             {
694cdf0e10cSrcweir                 sysDir = sysDir.substring(1);
695cdf0e10cSrcweir             }
696cdf0e10cSrcweir             else
697cdf0e10cSrcweir             {
698cdf0e10cSrcweir                 //network path
699cdf0e10cSrcweir                 sysDir = "//" + sysDir;
700cdf0e10cSrcweir             }
701cdf0e10cSrcweir             sysDir = sysDir.replace('/', '\\');
702cdf0e10cSrcweir         }
703cdf0e10cSrcweir 
704cdf0e10cSrcweir         return sysDir;
705cdf0e10cSrcweir     }
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     /**
708cdf0e10cSrcweir      * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
709cdf0e10cSrcweir      * this function asks the office for its location and fill the
710cdf0e10cSrcweir      * <CODE>AppExecutionCommand</CODE> with valid contet.
711cdf0e10cSrcweir      * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
712cdf0e10cSrcweir      * @param msf the <CODE>MultiServiceFactory</CODE>
713cdf0e10cSrcweir      * @param param the <CODE>TestParameters</CODE>
714cdf0e10cSrcweir      */
715cdf0e10cSrcweir     private static void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
716cdf0e10cSrcweir     {
717cdf0e10cSrcweir         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
718cdf0e10cSrcweir 
719cdf0e10cSrcweir         // get existing AppExecutionCommand if available, else empty string
720cdf0e10cSrcweir         String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
721cdf0e10cSrcweir 
722cdf0e10cSrcweir         String connectionString;
723cdf0e10cSrcweir         if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION) == true)
724cdf0e10cSrcweir         {
725cdf0e10cSrcweir             // This is the default behaviour
726cdf0e10cSrcweir             connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
727cdf0e10cSrcweir         }
728cdf0e10cSrcweir         else
729cdf0e10cSrcweir         {
730cdf0e10cSrcweir             // is used if UsePipeConnection=false
731cdf0e10cSrcweir             connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
732cdf0e10cSrcweir         }
733cdf0e10cSrcweir 
734cdf0e10cSrcweir         String sysBinDir = "";
735cdf0e10cSrcweir 
736cdf0e10cSrcweir         try
737cdf0e10cSrcweir         {
738cdf0e10cSrcweir             sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
739cdf0e10cSrcweir         }
740cdf0e10cSrcweir         catch (java.lang.Exception e)
741cdf0e10cSrcweir         {
742cdf0e10cSrcweir             dbg("could not get system binary directory");
743cdf0e10cSrcweir             return;
744cdf0e10cSrcweir         }
745cdf0e10cSrcweir 
746cdf0e10cSrcweir         // does the existing command show to the connected office?
747cdf0e10cSrcweir         if (command.indexOf(sysBinDir) == -1)
748cdf0e10cSrcweir         {
749cdf0e10cSrcweir             command = sysBinDir + System.getProperty("file.separator") + "soffice" +
750cdf0e10cSrcweir                     " -norestore -accept=" + connectionString + ";urp;";
751cdf0e10cSrcweir         }
752cdf0e10cSrcweir 
753cdf0e10cSrcweir         dbg("update AppExecutionCommand: " + command);
754cdf0e10cSrcweir 
755cdf0e10cSrcweir         param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
756cdf0e10cSrcweir     }
757cdf0e10cSrcweir 
758cdf0e10cSrcweir     private static void dbg(String message)
759cdf0e10cSrcweir     {
760cdf0e10cSrcweir         if (debug)
761cdf0e10cSrcweir         {
762cdf0e10cSrcweir             System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
763cdf0e10cSrcweir         }
764cdf0e10cSrcweir 
765cdf0e10cSrcweir     }
766cdf0e10cSrcweir 
767cdf0e10cSrcweir     private class OfficeWatcherPing extends Thread
768cdf0e10cSrcweir     {
769cdf0e10cSrcweir 
770cdf0e10cSrcweir         private final OfficeWatcher ow;
771cdf0e10cSrcweir         private boolean bStop = false;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir         public OfficeWatcherPing(OfficeWatcher ow)
774cdf0e10cSrcweir         {
775cdf0e10cSrcweir             this.ow = ow;
776cdf0e10cSrcweir         }
777cdf0e10cSrcweir 
778cdf0e10cSrcweir         @Override
779cdf0e10cSrcweir         public void run()
780cdf0e10cSrcweir         {
781cdf0e10cSrcweir             System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
782cdf0e10cSrcweir 
783cdf0e10cSrcweir             while (!bStop)
784cdf0e10cSrcweir             {
785cdf0e10cSrcweir                 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
786cdf0e10cSrcweir                 ow.ping();
787cdf0e10cSrcweir                 try
788cdf0e10cSrcweir                 {
789cdf0e10cSrcweir                     System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
790cdf0e10cSrcweir                     OfficeWatcherPing.sleep(1000); // 5000
791cdf0e10cSrcweir                 }
792cdf0e10cSrcweir                 catch (InterruptedException ex)
793cdf0e10cSrcweir                 {
794cdf0e10cSrcweir                     ex.printStackTrace();
795cdf0e10cSrcweir                 }
796cdf0e10cSrcweir             }
797cdf0e10cSrcweir 
798cdf0e10cSrcweir         }
799cdf0e10cSrcweir 
800cdf0e10cSrcweir         public void finish()
801cdf0e10cSrcweir         {
802cdf0e10cSrcweir             synchronized(this)
803cdf0e10cSrcweir             {
804cdf0e10cSrcweir                 bStop = true;
805cdf0e10cSrcweir                 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
806cdf0e10cSrcweir 
807cdf0e10cSrcweir                 notify();
808cdf0e10cSrcweir             }
809cdf0e10cSrcweir         }
810cdf0e10cSrcweir     }
811cdf0e10cSrcweir 
812cdf0e10cSrcweir private void deleteFilesAndDirector(File file)
813cdf0e10cSrcweir         {
814cdf0e10cSrcweir             File f = file;
815cdf0e10cSrcweir             if(f.isDirectory())
816cdf0e10cSrcweir             {
817cdf0e10cSrcweir                 File files[] = f.listFiles();
818cdf0e10cSrcweir                 for(int i = 0; i < files.length; i++)
819cdf0e10cSrcweir                 {
820cdf0e10cSrcweir                     deleteFilesAndDirector(files[i]);
821cdf0e10cSrcweir                 }
822cdf0e10cSrcweir                 f.delete();
823cdf0e10cSrcweir             }
824cdf0e10cSrcweir             else if (f.isFile())
825cdf0e10cSrcweir             {
826cdf0e10cSrcweir                 f.delete();
827cdf0e10cSrcweir             }
828cdf0e10cSrcweir         }
829cdf0e10cSrcweir }
830