bump product version to 5.0.4.1
[LibreOffice.git] / qadevOOo / runner / helper / OfficeProvider.java
blobd2dd4599776450c0c0d2b276405caf6e2ef23de8
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 package helper;
20 import com.sun.star.beans.XFastPropertySet;
21 import com.sun.star.bridge.XUnoUrlResolver;
22 import com.sun.star.container.XEnumeration;
23 import com.sun.star.container.XEnumerationAccess;
24 import com.sun.star.frame.XDesktop;
25 import com.sun.star.lang.XMultiComponentFactory;
26 import com.sun.star.lang.XMultiServiceFactory;
27 import com.sun.star.uno.UnoRuntime;
28 import com.sun.star.uno.XComponentContext;
29 import com.sun.star.util.XCloseable;
30 import com.sun.star.util.XStringSubstitution;
32 import java.io.File;
33 import java.io.PrintWriter;
35 import lib.TestParameters;
37 import share.DescEntry;
38 import share.LogWriter;
40 import util.DynamicClassLoader;
41 import util.PropertyName;
42 import util.utils;
44 /**
45 * This class will connect the office and start it if possible
48 public class OfficeProvider implements AppProvider
51 private boolean debug = false;
53 /**
54 * copy the user layer to a safe place, usually to $TMP/user_backup$USER
56 private void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
58 try
60 final XStringSubstitution sts = createStringSubstitution(msf);
61 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
63 String userLayer = sts.getSubstituteVariableValue("$(user)");
64 userLayer = getDirSys(userLayer);
65 param.put("userLayer", userLayer);
67 final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
68 "user_backup" +
69 System.getProperty("user.name");
70 param.put("copyLayer", copyLayer);
73 dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
74 // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
75 OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
76 owp.start();
78 deleteFilesAndDirector (new File(copyLayer));
79 FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
81 "temp"
82 });
84 owp.finish();
87 catch (com.sun.star.container.NoSuchElementException e)
89 System.out.println("User Variable '$(user)' not defined.");
91 catch (java.io.IOException e)
93 System.out.println("Couldn't backup user layer");
94 e.printStackTrace();
98 /**
99 * Dispose the office.
100 * This method can only be used, if the office was connected in the first
101 * place: getManager() was called first.
102 * @return return true if desktop is terminates, else false
104 public boolean disposeManager(lib.TestParameters param)
107 XMultiServiceFactory msf = param.getMSF();
109 if (msf == null)
111 return true;
113 else
115 XDesktop desk = null;
119 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
121 catch (com.sun.star.uno.Exception ue)
123 return false;
126 msf = null;
128 if (desk != null)
130 desk.terminate();
132 return true;
134 else
136 return false;
142 * Method to get the ServiceManager of an Office
144 public Object getManager(lib.TestParameters param)
146 String errorMessage = null;
147 boolean bAppExecutionHasWarning = false;
148 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
150 String additionalArgs = (String) param.get(
151 "AdditionalConnectionArguments");
153 if (additionalArgs == null)
155 additionalArgs = ";";
157 else
159 additionalArgs = "," + additionalArgs + ";";
162 final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
163 additionalArgs + "StarOffice.ServiceManager";
165 System.out.println("Connecting the Office with " + cncstr);
167 XMultiServiceFactory msf = connectOffice(cncstr);
169 // if the office is running and the office crashes while testing it could
170 // be usesfull to restart the office if possible and continuing the tests.
171 // Example: The UNO-API-Tests in the projects will be executed by calling
172 // 'damke'. This connects to an existing office. If the office crashes
173 // it is useful to restart the office and continuing the tests.
174 if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
176 makeAppExecCommand(msf, param);
179 if (msf == null)
181 String exc = "";
182 Exception exConnectFailed = null;
183 boolean isExecutable = false;
184 boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
185 isAppKnown &= ((String) param.get("AppExecutionCommand")).length() != 0;
187 if (isAppKnown)
189 dbg("Local Connection trying to start the Office");
191 //ensure that a pending officewatcher gets finished before a new
192 //office is started
193 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
195 if (ow_old != null)
197 ow_old.finish = true;
200 final String cmd = (String) param.get("AppExecutionCommand");
201 dbg("AppExecutionCommand: " + cmd);
202 // validate the AppExecutionCommand, but try it out anyway.
203 // keep the error message for later.
204 errorMessage =
205 util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
206 if (errorMessage.startsWith("Error"))
208 System.out.println(errorMessage);
209 return null;
211 bAppExecutionHasWarning = !errorMessage.equals("OK");
213 final DynamicClassLoader dcl = new DynamicClassLoader();
214 final LogWriter log = (LogWriter) dcl.getInstance(
215 (String) param.get("LogWriter"));
217 //create empty entry
218 final DescEntry Entry = new DescEntry();
219 Entry.entryName = "office";
220 Entry.longName = "office";
221 Entry.EntryType = "placebo";
222 Entry.isOptional = false;
223 Entry.isToTest = false;
224 Entry.SubEntryCount = 0;
225 Entry.hasErrorMsg = false;
226 Entry.State = "non possible";
227 Entry.UserDefinedParams = param;
229 log.initialize(Entry, debug);
231 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
232 isExecutable = ph.executeAsynchronously();
234 if (isExecutable)
236 param.put("AppProvider", ph);
237 final OfficeWatcher ow = new OfficeWatcher(param);
238 param.put("Watcher", ow);
239 ow.start();
240 ow.ping();
243 int k = 0;
245 // wait up to 21 seconds to get an office connection
246 while ((k < 42) && (msf == null))
250 msf = connect(cncstr);
252 catch (com.sun.star.uno.Exception ue)
254 exConnectFailed = ue;
255 exc = ue.getMessage();
257 catch (java.lang.Exception je)
259 exConnectFailed = je;
260 exc = je.getMessage();
262 if (msf == null)
264 util.utils.pause(500 * k);
266 k++;
269 if (msf == null)
271 System.out.println("Exception while connecting.\n" + exConnectFailed);
272 if (exc != null)
274 System.out.println(exc);
276 if (bAppExecutionHasWarning)
278 System.out.println(errorMessage);
281 else if (isExecutable)
283 backupUserLayer(param, msf);
286 else
288 System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
289 concat("\nsoffice --accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
293 return msf;
297 * Connect an Office
298 * @param connectStr
299 * @return
300 * @throws com.sun.star.uno.Exception
301 * @throws com.sun.star.uno.RuntimeException
302 * @throws com.sun.star.connection.NoConnectException
303 * @throws Exception
305 private XMultiServiceFactory connect(String connectStr)
306 throws com.sun.star.uno.Exception,
307 com.sun.star.uno.RuntimeException,
308 com.sun.star.connection.NoConnectException,
309 Exception
312 // Get component context
313 final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
315 // initial serviceManager
316 final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
318 // create a connector, so that it can contact the office
319 final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
320 final XUnoUrlResolver urlResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, xUrlResolver);
322 final Object rInitialObject = urlResolver.resolve(connectStr);
324 XMultiServiceFactory xMSF = null;
326 if (rInitialObject != null)
328 // debug = true;
329 dbg("resolved url");
331 xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
334 return xMSF;
338 * Close an office.
339 * @param param The test parameters.
340 * @param closeIfPossible If true, close even if
341 * it was running before the test
343 public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
346 XMultiServiceFactory msf = param.getMSF();
347 final boolean alreadyConnected = (msf != null);
348 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
350 if (alreadyConnected)
352 dbg("try to get ProcessHandler");
354 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
356 if (ph != null)
358 dbg("ProcessHandler != null");
360 disposeOffice(msf, param);
362 // dispose watcher in case it's still running.
363 dbg("try to get OfficeWatcher");
365 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
367 if ((ow != null) && ow.isAlive())
369 dbg("OfficeWatcher will be finished");
370 ow.finish = true;
372 else
374 dbg("OfficeWatcher seems to be finished");
377 return true;
379 else
381 if (closeIfPossible)
383 return disposeOffice(msf, param);
387 else
389 final String cncstr = "uno:" + param.get("ConnectionString") +
390 ";urp;StarOffice.ServiceManager";
391 dbg("try to connect office");
392 msf = connectOffice(cncstr);
394 if (closeIfPossible)
396 return disposeOffice(msf, param);
399 dbg("closeExistingOffice finished");
400 return true;
403 private XMultiServiceFactory connectOffice(String cncstr)
405 XMultiServiceFactory msf = null;
406 String exc = "";
407 // debug = true;
409 dbg("trying to connect to " + cncstr);
413 msf = connect(cncstr);
415 catch (com.sun.star.uno.Exception ue)
417 exc = ue.getMessage();
419 catch (java.lang.Exception je)
421 exc = je.getMessage();
424 if (debug && exc != null && exc.length() != 0)
426 dbg("Could not connect an Office. " + exc);
429 return msf;
432 private synchronized boolean disposeOffice(XMultiServiceFactory msf,
433 TestParameters param)
435 XDesktop desk = null;
437 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
439 boolean result = true;
441 if (msf != null)
444 // disable QuickStarter
447 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
448 XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
449 fps.setFastPropertyValue(0, false);
451 catch (com.sun.star.uno.Exception ex)
453 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
458 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
459 msf = null;
461 if (desk != null)
463 final boolean allClosed = closeAllWindows(desk);
465 if (!allClosed)
467 dbg("Couldn't close all office windows!");
470 dbg("Trying to terminate the desktop");
472 desk.terminate();
473 dbg("Desktop terminated");
477 final int closeTime = param.getInt(util.PropertyName.OFFICE_CLOSE_TIME_OUT);
478 dbg("the Office has " + closeTime / 1000 + " seconds for closing...");
479 Thread.sleep(closeTime);
481 catch (InterruptedException e)
486 catch (com.sun.star.uno.Exception ue)
488 result = false;
490 catch (com.sun.star.lang.DisposedException ue)
492 result = false;
496 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
498 if (ph != null)
500 // dispose watcher in case it's still running.
501 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
503 if ((ow != null) && ow.isAlive())
505 ow.finish = true;
508 ph.kill();
511 param.remove("AppProvider");
512 param.remove("ServiceFactory");
514 //copy user_backup into user layer
517 final String userLayer = (String) param.get("userLayer");
518 final String copyLayer = (String) param.get("copyLayer");
519 if (userLayer != null && copyLayer != null)
521 deleteFilesAndDirector(new File(userLayer));
522 final File copyFile = new File(copyLayer);
523 dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
524 FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
526 "temp"
528 dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
530 // remove all user_backup folder in temp dir
531 // this is for the case the runner was killed and some old backup folder still stay in temp dir
535 else
537 System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
540 catch (java.io.IOException e)
542 dbg("Couldn't recover from backup\n" + e.getMessage());
544 return result;
547 private boolean closeAllWindows(XDesktop desk)
549 final XEnumerationAccess compEnumAccess = desk.getComponents();
550 final XEnumeration compEnum = compEnumAccess.createEnumeration();
551 boolean res = true;
555 while (compEnum.hasMoreElements())
557 final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
559 if (closer != null)
561 closer.close(true);
565 catch (com.sun.star.util.CloseVetoException cve)
567 res = false;
569 catch (com.sun.star.container.NoSuchElementException nsee)
571 res = false;
573 catch (com.sun.star.lang.WrappedTargetException wte)
575 res = false;
578 return res;
581 private static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
583 Object xPathSubst = null;
587 xPathSubst = xMSF.createInstance(
588 "com.sun.star.util.PathSubstitution");
590 catch (com.sun.star.uno.Exception e)
592 e.printStackTrace();
595 if (xPathSubst != null)
597 return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
599 else
601 return null;
606 * converts directory without 'file:///' prefix.
607 * and System dependent file separator
609 private static String getDirSys(String dir)
611 String sysDir = "";
613 final int idx = dir.indexOf("file://");
615 final int idx2 = dir.indexOf("file:///");
617 // remove leading 'file://'
618 if (idx < 0)
620 sysDir = dir;
622 else
624 sysDir = dir.substring("file://".length());
627 sysDir = sysDir.replace("%20", " ");
629 // append '/' if not there (e.g. linux)
630 if (sysDir.charAt(sysDir.length() - 1) != '/')
632 sysDir += "/";
635 // remove leading '/' and replace others with '\' on windows machines
636 final String sep = System.getProperty("file.separator");
638 if (sep.equalsIgnoreCase("\\"))
640 if (idx2 >= 0)
642 sysDir = sysDir.substring(1);
644 else
646 //network path
647 sysDir = "//" + sysDir;
649 sysDir = sysDir.replace('/', '\\');
652 return sysDir;
656 * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
657 * this function asks the office for its location and fill the
658 * <CODE>AppExecutionCommand</CODE> with valid contet.
659 * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
660 * @param msf the <CODE>MultiServiceFactory</CODE>
661 * @param param the <CODE>TestParameters</CODE>
663 private void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
665 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
667 // get existing AppExecutionCommand if available, else empty string
668 String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
670 String connectionString;
671 if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION))
673 // This is the default behaviour
674 connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
676 else
678 // is used if UsePipeConnection=false
679 connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
682 String sysBinDir = "";
686 sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
688 catch (java.lang.Exception e)
690 dbg("could not get system binary directory");
691 return;
694 // does the existing command show to the connected office?
695 if (command.indexOf(sysBinDir) == -1)
697 command = sysBinDir + System.getProperty("file.separator") + "soffice" +
698 " --norestore --accept=" + connectionString + ";urp;";
701 dbg("update AppExecutionCommand: " + command);
703 param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
706 private void dbg(String message)
708 if (debug)
710 System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
715 private class OfficeWatcherPing extends Thread
718 private final OfficeWatcher ow;
719 private boolean bStop = false;
721 public OfficeWatcherPing(OfficeWatcher ow)
723 this.ow = ow;
726 @Override
727 public void run()
729 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
731 while (!bStop)
733 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
734 ow.ping();
735 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
736 util.utils.pause(1000);
741 public void finish()
743 synchronized(this)
745 bStop = true;
746 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
748 notify();
753 private void deleteFilesAndDirector(File file)
755 File f = file;
756 if(f.isDirectory())
758 File files[] = f.listFiles();
759 for(int i = 0; i < files.length; i++)
761 deleteFilesAndDirector(files[i]);
763 f.delete();
765 else if (f.isFile())
767 f.delete();