bump product version to 4.2.0.1
[LibreOffice.git] / qadevOOo / runner / helper / OfficeProvider.java
blobc0e573d8c2129210010b6530bf3b62c41ff9bc71
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.bridge.UnoUrlResolver;
21 import com.sun.star.beans.XFastPropertySet;
22 import com.sun.star.bridge.XUnoUrlResolver;
23 import com.sun.star.container.XEnumeration;
24 import com.sun.star.container.XEnumerationAccess;
25 import com.sun.star.frame.XDesktop;
26 import com.sun.star.lang.XMultiComponentFactory;
27 import com.sun.star.lang.XMultiServiceFactory;
28 import com.sun.star.uno.UnoRuntime;
29 import com.sun.star.uno.XComponentContext;
30 import com.sun.star.util.XCloseable;
31 import com.sun.star.util.XStringSubstitution;
33 import java.io.File;
34 import java.io.PrintWriter;
35 import java.util.StringTokenizer;
37 import lib.TestParameters;
39 import share.DescEntry;
40 import share.LogWriter;
42 import util.DynamicClassLoader;
43 import util.PropertyName;
44 import util.utils;
46 /**
47 * This class will connect the office and start it if possible
50 public class OfficeProvider implements AppProvider
53 private static boolean debug = false;
55 /**
56 * copy the user layer to a safe place, usualy to $TMP/user_backup$USER
57 * @param param
58 * @param msf
60 public void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
62 try
64 final XStringSubstitution sts = createStringSubstitution(msf);
65 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
67 String userLayer = sts.getSubstituteVariableValue("$(user)");
68 userLayer = getDirSys(userLayer);
69 param.put("userLayer", userLayer);
71 final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
72 "user_backup" +
73 System.getProperty("user.name");
74 param.put("copyLayer", copyLayer);
77 dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
78 // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
79 OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
80 owp.start();
82 deleteFilesAndDirector (new File(copyLayer));
83 FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
85 "temp"
86 });
88 owp.finish();
91 catch (com.sun.star.container.NoSuchElementException e)
93 System.out.println("User Variable '$(user)' not defined.");
95 catch (java.io.IOException e)
97 System.out.println("Couldn't backup user layer");
98 e.printStackTrace();
103 * Dispose the office.
104 * This method can only be used, if the office was connected in the first
105 * place: getManager() was called first.
106 * @param param
107 * @return return true if desktop is terminates, else false
109 public boolean disposeManager(lib.TestParameters param)
112 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
114 if (msf == null)
116 return true;
118 else
120 XDesktop desk = null;
124 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
126 catch (com.sun.star.uno.Exception ue)
128 return false;
131 msf = null;
133 if (desk != null)
135 desk.terminate();
137 return true;
139 else
141 return false;
147 * Method to get the ServiceManager of an Office
148 * @param param
149 * @return
151 public Object getManager(lib.TestParameters param)
153 String errorMessage = null;
154 boolean bAppExecutionHasWarning = false;
155 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
157 String additionalArgs = (String) param.get(
158 "AdditionalConnectionArguments");
160 if (additionalArgs == null)
162 additionalArgs = ";";
164 else
166 additionalArgs = "," + additionalArgs + ";";
169 final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
170 additionalArgs + "StarOffice.ServiceManager";
172 System.out.println("Connecting the Office with " + cncstr);
174 XMultiServiceFactory msf = connectOffice(cncstr);
176 // if the office is running and the office crashes while testing it could
177 // be usesfull to restart the office if possible and continuing the tests.
178 // Example: The UNO-API-Tests in the projects will be executed by calling
179 // 'damke'. This connects to an existing office. If the office crashes
180 // it is useful to restart the office and continuing the tests.
181 if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
183 makeAppExecCommand(msf, param);
186 if (msf == null)
188 String exc = "";
189 Exception exConnectFailed = null;
190 boolean isExecutable = false;
191 boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
192 isAppKnown &= !((String) param.get("AppExecutionCommand")).equals("");
194 if (isAppKnown)
196 dbg("Local Connection trying to start the Office");
198 //ensure that a pending officewatcher gets finished before a new
199 //office is started
200 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
202 if (ow_old != null)
204 ow_old.finish = true;
207 final String cmd = (String) param.get("AppExecutionCommand");
208 dbg("AppExecutionCommand: " + cmd);
209 // validate the AppExecutionCommand, but try it out anyway.
210 // keep the error message for later.
211 errorMessage =
212 util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
213 if (errorMessage.startsWith("Error"))
215 System.out.println(errorMessage);
216 return null;
218 bAppExecutionHasWarning = !errorMessage.equals("OK");
220 final DynamicClassLoader dcl = new DynamicClassLoader();
221 final LogWriter log = (LogWriter) dcl.getInstance(
222 (String) param.get("LogWriter"));
224 //create empty entry
225 final DescEntry Entry = new DescEntry();
226 Entry.entryName = "office";
227 Entry.longName = "office";
228 Entry.EntryType = "placebo";
229 Entry.isOptional = false;
230 Entry.isToTest = false;
231 Entry.SubEntryCount = 0;
232 Entry.hasErrorMsg = false;
233 Entry.State = "non possible";
234 Entry.UserDefinedParams = param;
236 log.initialize(Entry, debug);
238 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
239 isExecutable = ph.executeAsynchronously();
241 if (isExecutable)
243 param.put("AppProvider", ph);
244 final OfficeWatcher ow = new OfficeWatcher(param);
245 param.put("Watcher", ow);
246 ow.start();
247 ow.ping();
250 int k = 0;
252 // wait up to 21 seconds to get an office connection
253 while ((k < 42) && (msf == null))
257 msf = connect(cncstr);
259 catch (com.sun.star.uno.Exception ue)
261 exConnectFailed = ue;
262 exc = ue.getMessage();
264 catch (java.lang.Exception je)
266 exConnectFailed = je;
267 exc = je.getMessage();
269 if (msf == null)
273 Thread.sleep(k * 500);
275 catch (InterruptedException ex)
279 k++;
282 if (msf == null)
284 System.out.println("Exception while connecting.\n" + exConnectFailed);
285 if (exc != null)
287 System.out.println(exc);
289 if (bAppExecutionHasWarning)
291 System.out.println(errorMessage);
294 else if (isExecutable)
296 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
298 backupUserLayer(param, msf);
302 else
304 System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
305 concat("\nsoffice --accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
306 if (bAppExecutionHasWarning)
308 System.out.println(errorMessage);
313 return msf;
317 * Connect an Office
318 * @param connectStr
319 * @return
320 * @throws com.sun.star.uno.Exception
321 * @throws com.sun.star.uno.RuntimeException
322 * @throws com.sun.star.connection.NoConnectException
323 * @throws Exception
325 protected static XMultiServiceFactory connect(String connectStr)
326 throws com.sun.star.uno.Exception,
327 com.sun.star.uno.RuntimeException,
328 com.sun.star.connection.NoConnectException,
329 Exception
332 // Get component context
333 final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
335 // initial serviceManager
336 final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
338 // create a connector, so that it can contact the office
339 // XUnoUrlResolver urlResolver = UnoUrlResolver.create(xcomponentcontext);
340 final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
341 final XUnoUrlResolver urlResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, xUrlResolver);
343 final Object rInitialObject = urlResolver.resolve(connectStr);
345 XMultiServiceFactory xMSF = null;
347 if (rInitialObject != null)
349 // debug = true;
350 dbg("resolved url");
352 xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
355 return xMSF;
359 * Close an office.
360 * @param param The test parameters.
361 * @param closeIfPossible If true, close even if
362 * it was running before the test
364 public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
367 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
368 final boolean alreadyConnected = (msf != null);
369 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
371 if (alreadyConnected)
373 dbg("try to get ProcessHandler");
375 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
377 if (ph != null)
379 dbg("ProcessHandler != null");
381 disposeOffice(msf, param);
383 // dispose watcher in case it's still running.
384 dbg("try to get OfficeWatcher");
386 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
388 if ((ow != null) && ow.isAlive())
390 dbg("OfficeWatcher will be finished");
391 ow.finish = true;
393 else
395 dbg("OfficeWatcher seems to be finished");
398 return true;
400 else
402 if (closeIfPossible)
404 return disposeOffice(msf, param);
408 else
410 final String cncstr = "uno:" + param.get("ConnectionString") +
411 ";urp;StarOffice.ServiceManager";
412 dbg("try to connect office");
413 msf = connectOffice(cncstr);
415 if (closeIfPossible)
417 return disposeOffice(msf, param);
420 dbg("closeExistingOffice finished");
421 return true;
424 private XMultiServiceFactory connectOffice(String cncstr)
426 XMultiServiceFactory msf = null;
427 String exc = "";
428 // debug = true;
430 dbg("trying to connect to " + cncstr);
434 msf = connect(cncstr);
436 catch (com.sun.star.uno.Exception ue)
438 exc = ue.getMessage();
440 catch (java.lang.Exception je)
442 exc = je.getMessage();
445 if (debug && exc != null && exc.length() != 0)
447 dbg("Could not connect an Office. " + exc);
450 return msf;
453 private synchronized boolean disposeOffice(XMultiServiceFactory msf,
454 TestParameters param)
456 XDesktop desk = null;
458 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
460 boolean result = true;
462 if (msf != null)
465 // disable QuickStarter
468 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
469 XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
470 fps.setFastPropertyValue(0, false);
472 catch (com.sun.star.uno.Exception ex)
474 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
479 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
480 msf = null;
482 if (desk != null)
484 final boolean allClosed = closeAllWindows(desk);
486 if (!allClosed)
488 dbg("Couldn't close all office windows!");
491 dbg("Trying to terminate the desktop");
493 desk.terminate();
494 dbg("Desktop terminated");
498 final int closeTime = param.getInt(util.PropertyName.OFFICE_CLOSE_TIME_OUT);
499 dbg("the Office has " + closeTime / 1000 + " seconds for closing...");
500 Thread.sleep(closeTime);
502 catch (java.lang.InterruptedException e)
507 catch (com.sun.star.uno.Exception ue)
509 result = false;
511 catch (com.sun.star.lang.DisposedException ue)
513 result = false;
517 final String AppKillCommand = (String) param.get(util.PropertyName.APP_KILL_COMMAND);
518 if (AppKillCommand != null)
520 String sAppKillCommand = StringHelper.removeSurroundQuoteIfExists(AppKillCommand);
521 final StringTokenizer aKillCommandToken = new StringTokenizer(sAppKillCommand, ";");
522 while (aKillCommandToken.hasMoreTokens())
524 final String sKillCommand = aKillCommandToken.nextToken();
525 dbg("User defined an application to destroy the started process. Trying to execute: " + sKillCommand);
527 final ProcessHandler pHdl = new ProcessHandler(sKillCommand, 1000); // 3000 seems to be too long
528 pHdl.runCommand();
530 pHdl.kill();
534 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
536 if (ph != null)
538 // dispose watcher in case it's still running.
539 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
541 if ((ow != null) && ow.isAlive())
543 ow.finish = true;
546 ph.kill();
549 param.remove("AppProvider");
550 param.remove("ServiceFactory");
552 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
554 //copy user_backup into user layer
557 final String userLayer = (String) param.get("userLayer");
558 final String copyLayer = (String) param.get("copyLayer");
559 if (userLayer != null && copyLayer != null)
561 deleteFilesAndDirector(new File(userLayer));
562 final File copyFile = new File(copyLayer);
563 dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
564 FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
566 "temp"
568 dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
570 // remove all user_backup folder in temp dir
571 // this is for the case the runner was killed and some old backup folder still stay in temp dir
575 else
577 System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
580 catch (java.io.IOException e)
582 dbg("Couldn't recover from backup\n" + e.getMessage());
585 return result;
588 protected boolean closeAllWindows(XDesktop desk)
590 final XEnumerationAccess compEnumAccess = desk.getComponents();
591 final XEnumeration compEnum = compEnumAccess.createEnumeration();
592 boolean res = true;
596 while (compEnum.hasMoreElements())
598 final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
600 if (closer != null)
602 closer.close(true);
606 catch (com.sun.star.util.CloseVetoException cve)
608 res = false;
610 catch (com.sun.star.container.NoSuchElementException nsee)
612 res = false;
614 catch (com.sun.star.lang.WrappedTargetException wte)
616 res = false;
619 return res;
622 public static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
624 Object xPathSubst = null;
628 xPathSubst = xMSF.createInstance(
629 "com.sun.star.util.PathSubstitution");
631 catch (com.sun.star.uno.Exception e)
633 e.printStackTrace();
636 if (xPathSubst != null)
638 return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
640 else
642 return null;
647 * converts directory without 'file:///' prefix.
648 * and System dependend file separator
649 * @param dir
650 * @return
652 public static String getDirSys(String dir)
654 String sysDir = "";
656 final int idx = dir.indexOf("file://");
658 final int idx2 = dir.indexOf("file:///");
660 // remove leading 'file://'
661 if (idx < 0)
663 sysDir = dir;
665 else
667 sysDir = dir.substring("file://".length());
670 sysDir = utils.replaceAll13(sysDir, "%20", " ");
672 // append '/' if not there (e.g. linux)
673 if (sysDir.charAt(sysDir.length() - 1) != '/')
675 sysDir += "/";
678 // remove leading '/' and replace others with '\' on windows machines
679 final String sep = System.getProperty("file.separator");
681 if (sep.equalsIgnoreCase("\\"))
683 if (!(idx2 < 0))
685 sysDir = sysDir.substring(1);
687 else
689 //network path
690 sysDir = "//" + sysDir;
692 sysDir = sysDir.replace('/', '\\');
695 return sysDir;
699 * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
700 * this function asks the office for its location and fill the
701 * <CODE>AppExecutionCommand</CODE> with valid contet.
702 * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
703 * @param msf the <CODE>MultiServiceFactory</CODE>
704 * @param param the <CODE>TestParameters</CODE>
706 private static void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
708 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
710 // get existing AppExecutionCommand if available, else empty string
711 String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
713 String connectionString;
714 if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION) == true)
716 // This is the default behaviour
717 connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
719 else
721 // is used if UsePipeConnection=false
722 connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
725 String sysBinDir = "";
729 sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
731 catch (java.lang.Exception e)
733 dbg("could not get system binary directory");
734 return;
737 // does the existing command show to the connected office?
738 if (command.indexOf(sysBinDir) == -1)
740 command = sysBinDir + System.getProperty("file.separator") + "soffice" +
741 " --norestore --accept=" + connectionString + ";urp;";
744 dbg("update AppExecutionCommand: " + command);
746 param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
749 private static void dbg(String message)
751 if (debug)
753 System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
758 private class OfficeWatcherPing extends Thread
761 private final OfficeWatcher ow;
762 private boolean bStop = false;
764 public OfficeWatcherPing(OfficeWatcher ow)
766 this.ow = ow;
769 @Override
770 public void run()
772 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
774 while (!bStop)
776 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
777 ow.ping();
780 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
781 OfficeWatcherPing.sleep(1000); // 5000
783 catch (InterruptedException ex)
785 ex.printStackTrace();
791 public void finish()
793 synchronized(this)
795 bStop = true;
796 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
798 notify();
803 private void deleteFilesAndDirector(File file)
805 File f = file;
806 if(f.isDirectory())
808 File files[] = f.listFiles();
809 for(int i = 0; i < files.length; i++)
811 deleteFilesAndDirector(files[i]);
813 f.delete();
815 else if (f.isFile())
817 f.delete();