Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / qadevOOo / runner / helper / OfficeProvider.java
blob3d469725b7eecd88a080ecaa1c367eaa413df49a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
27 package helper;
29 //import com.sun.star.bridge.UnoUrlResolver;
30 import com.sun.star.beans.XFastPropertySet;
31 import com.sun.star.bridge.XUnoUrlResolver;
32 import com.sun.star.container.XEnumeration;
33 import com.sun.star.container.XEnumerationAccess;
34 import com.sun.star.frame.XDesktop;
35 import com.sun.star.lang.XMultiComponentFactory;
36 import com.sun.star.lang.XMultiServiceFactory;
37 import com.sun.star.uno.UnoRuntime;
38 import com.sun.star.uno.XComponentContext;
39 import com.sun.star.util.XCloseable;
40 import com.sun.star.util.XStringSubstitution;
42 import java.io.File;
43 import java.io.PrintWriter;
44 import java.util.StringTokenizer;
46 import lib.TestParameters;
48 import share.DescEntry;
49 import share.LogWriter;
51 import util.DynamicClassLoader;
52 import util.PropertyName;
53 import util.utils;
55 /**
56 * This class will connect the office and start it if possible
59 public class OfficeProvider implements AppProvider
62 private static boolean debug = false;
64 /**
65 * copy the user layer to a safe place, usualy to $TMP/user_backup$USER
66 * @param param
67 * @param msf
69 public void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
71 try
73 final XStringSubstitution sts = createStringSubstitution(msf);
74 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
76 String userLayer = sts.getSubstituteVariableValue("$(user)");
77 userLayer = getDirSys(userLayer);
78 param.put("userLayer", userLayer);
80 final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
81 "user_backup" +
82 System.getProperty("user.name");
83 param.put("copyLayer", copyLayer);
86 dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
87 // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
88 OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
89 owp.start();
91 deleteFilesAndDirector (new File(copyLayer));
92 FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
94 "temp"
95 });
97 owp.finish();
100 catch (com.sun.star.container.NoSuchElementException e)
102 System.out.println("User Variable '$(user)' not defined.");
104 catch (java.io.IOException e)
106 System.out.println("Couldn't backup user layer");
107 e.printStackTrace();
112 * Dispose the office.
113 * This method can only be used, if the office was connected in the first
114 * place: getManager() was called first.
115 * @param param
116 * @return return true if desktop is terminates, else false
118 public boolean disposeManager(lib.TestParameters param)
121 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
123 if (msf == null)
125 return true;
127 else
129 XDesktop desk = null;
133 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
135 catch (com.sun.star.uno.Exception ue)
137 return false;
140 msf = null;
142 if (desk != null)
144 desk.terminate();
146 return true;
148 else
150 return false;
156 * Method to get the ServiceManager of an Office
157 * @param param
158 * @return
160 public Object getManager(lib.TestParameters param)
162 String errorMessage = null;
163 boolean bAppExecutionHasWarning = false;
164 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
166 String additionalArgs = (String) param.get(
167 "AdditionalConnectionArguments");
169 if (additionalArgs == null)
171 additionalArgs = ";";
173 else
175 additionalArgs = "," + additionalArgs + ";";
178 final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
179 additionalArgs + "StarOffice.ServiceManager";
181 System.out.println("Connecting the Office with " + cncstr);
183 XMultiServiceFactory msf = connectOffice(cncstr);
185 // if the office is running and the office crashes while testing it could
186 // be usesfull to restart the office if possible and continuing the tests.
187 // Example: The UNO-API-Tests in the projects will be executed by calling
188 // 'damke'. This connects to an existing office. If the office crashes
189 // it is usefull to restart the office and continuing the tests.
190 if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
192 makeAppExecCommand(msf, param);
195 if (msf == null)
197 String exc = "";
198 Exception exConnectFailed = null;
199 boolean isExecutable = false;
200 boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
201 isAppKnown &= !((String) param.get("AppExecutionCommand")).equals("");
203 if (isAppKnown)
205 dbg("Local Connection trying to start the Office");
207 //ensure that a pending officewatcher gets finished before a new
208 //office is started
209 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
211 if (ow_old != null)
213 ow_old.finish = true;
216 final String cmd = (String) param.get("AppExecutionCommand");
217 dbg("AppExecutionCommand: " + cmd);
218 // validate the AppExecutionCommand, but try it out anyway.
219 // keep the error message for later.
220 errorMessage =
221 util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
222 if (errorMessage.startsWith("Error"))
224 System.out.println(errorMessage);
225 return null;
227 bAppExecutionHasWarning = !errorMessage.equals("OK");
229 final DynamicClassLoader dcl = new DynamicClassLoader();
230 final LogWriter log = (LogWriter) dcl.getInstance(
231 (String) param.get("LogWriter"));
233 //create empty entry
234 final DescEntry Entry = new DescEntry();
235 Entry.entryName = "office";
236 Entry.longName = "office";
237 Entry.EntryType = "placebo";
238 Entry.isOptional = false;
239 Entry.isToTest = false;
240 Entry.SubEntryCount = 0;
241 Entry.hasErrorMsg = false;
242 Entry.State = "non possible";
243 Entry.UserDefinedParams = param;
245 log.initialize(Entry, debug);
247 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
248 isExecutable = ph.executeAsynchronously();
250 if (isExecutable)
252 param.put("AppProvider", ph);
253 final OfficeWatcher ow = new OfficeWatcher(param);
254 param.put("Watcher", ow);
255 ow.start();
256 ow.ping();
259 int k = 0;
261 // wait up to 21 seconds to get an office connection
262 while ((k < 42) && (msf == null))
266 msf = connect(cncstr);
268 catch (com.sun.star.uno.Exception ue)
270 exConnectFailed = ue;
271 exc = ue.getMessage();
273 catch (java.lang.Exception je)
275 exConnectFailed = je;
276 exc = je.getMessage();
278 if (msf == null)
282 Thread.sleep(k * 500);
284 catch (InterruptedException ex)
288 k++;
291 if (msf == null)
293 System.out.println("Exception while connecting.\n" + exConnectFailed);
294 if (exc != null)
296 System.out.println(exc);
298 if (bAppExecutionHasWarning)
300 System.out.println(errorMessage);
303 else if (isExecutable)
305 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
307 backupUserLayer(param, msf);
311 else
313 System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
314 concat("\nsoffice --accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
315 if (bAppExecutionHasWarning)
317 System.out.println(errorMessage);
322 return msf;
326 * Connect an Office
327 * @param connectStr
328 * @return
329 * @throws com.sun.star.uno.Exception
330 * @throws com.sun.star.uno.RuntimeException
331 * @throws com.sun.star.connection.NoConnectException
332 * @throws Exception
334 protected static XMultiServiceFactory connect(String connectStr)
335 throws com.sun.star.uno.Exception,
336 com.sun.star.uno.RuntimeException,
337 com.sun.star.connection.NoConnectException,
338 Exception
341 // Get component context
342 final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
344 // initial serviceManager
345 final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
347 // create a connector, so that it can contact the office
348 // XUnoUrlResolver urlResolver = UnoUrlResolver.create(xcomponentcontext);
349 final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
350 final XUnoUrlResolver urlResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, xUrlResolver);
352 final Object rInitialObject = urlResolver.resolve(connectStr);
354 XMultiServiceFactory xMSF = null;
356 if (rInitialObject != null)
358 // debug = true;
359 dbg("resolved url");
361 xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
364 return xMSF;
368 * Close an office.
369 * @param param The test parameters.
370 * @param closeIfPossible If true, close even if
371 * it was running before the test
373 public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
376 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
377 final boolean alreadyConnected = (msf != null);
378 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
380 if (alreadyConnected)
382 dbg("try to get ProcessHandler");
384 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
386 if (ph != null)
388 dbg("ProcessHandler != null");
390 disposeOffice(msf, param);
392 // dispose watcher in case it's still running.
393 dbg("try to get OfficeWatcher");
395 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
397 if ((ow != null) && ow.isAlive())
399 dbg("OfficeWatcher will be finished");
400 ow.finish = true;
402 else
404 dbg("OfficeWatcher seems to be finished");
407 return true;
409 else
411 if (closeIfPossible)
413 return disposeOffice(msf, param);
417 else
419 final String cncstr = "uno:" + param.get("ConnectionString") +
420 ";urp;StarOffice.ServiceManager";
421 dbg("try to connect office");
422 msf = connectOffice(cncstr);
424 if (closeIfPossible)
426 return disposeOffice(msf, param);
429 dbg("closeExistingOffice finished");
430 return true;
433 private XMultiServiceFactory connectOffice(String cncstr)
435 XMultiServiceFactory msf = null;
436 String exc = "";
437 // debug = true;
439 dbg("trying to connect to " + cncstr);
443 msf = connect(cncstr);
445 catch (com.sun.star.uno.Exception ue)
447 exc = ue.getMessage();
449 catch (java.lang.Exception je)
451 exc = je.getMessage();
454 if (debug && exc != null && exc.length() != 0)
456 if (exc == null)
458 exc = "";
460 dbg("Could not connect an Office. " + exc);
463 return msf;
466 private synchronized boolean disposeOffice(XMultiServiceFactory msf,
467 TestParameters param)
469 XDesktop desk = null;
471 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
473 boolean result = true;
475 if (msf != null)
478 // disable QuickStarter
481 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
482 XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
483 fps.setFastPropertyValue(0, false);
485 catch (com.sun.star.uno.Exception ex)
487 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
492 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
493 msf = null;
495 if (desk != null)
497 final boolean allClosed = closeAllWindows(desk);
499 if (!allClosed)
501 dbg("Couldn't close all office windows!");
504 dbg("Trying to terminate the desktop");
506 desk.terminate();
507 dbg("Desktop terminated");
511 final int closeTime = param.getInt(util.PropertyName.OFFICE_CLOSE_TIME_OUT);
512 dbg("the Office has " + closeTime / 1000 + " seconds for closing...");
513 Thread.sleep(closeTime);
515 catch (java.lang.InterruptedException e)
520 catch (com.sun.star.uno.Exception ue)
522 result = false;
524 catch (com.sun.star.lang.DisposedException ue)
526 result = false;
530 final String AppKillCommand = (String) param.get(util.PropertyName.APP_KILL_COMMAND);
531 if (AppKillCommand != null)
533 String sAppKillCommand = StringHelper.removeSurroundQuoteIfExists(AppKillCommand);
534 final StringTokenizer aKillCommandToken = new StringTokenizer(sAppKillCommand, ";");
535 while (aKillCommandToken.hasMoreTokens())
537 final String sKillCommand = aKillCommandToken.nextToken();
538 dbg("User defined an application to destroy the started process. Trying to execute: " + sKillCommand);
540 final ProcessHandler pHdl = new ProcessHandler(sKillCommand, 1000); // 3000 seems to be too long
541 pHdl.runCommand();
543 pHdl.kill();
547 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
549 if (ph != null)
551 // dispose watcher in case it's still running.
552 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
554 if ((ow != null) && ow.isAlive())
556 ow.finish = true;
559 ph.kill();
562 param.remove("AppProvider");
563 param.remove("ServiceFactory");
565 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
567 //copy user_backup into user layer
570 final String userLayer = (String) param.get("userLayer");
571 final String copyLayer = (String) param.get("copyLayer");
572 if (userLayer != null && copyLayer != null)
574 deleteFilesAndDirector(new File(userLayer));
575 final File copyFile = new File(copyLayer);
576 dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
577 FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
579 "temp"
581 dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
583 // remove all user_backup folder in temp dir
584 // this is for the case the runner was killed and some old backup folder still stay in temp dir
588 else
590 System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
593 catch (java.io.IOException e)
595 dbg("Couldn't recover from backup\n" + e.getMessage());
598 return result;
601 protected boolean closeAllWindows(XDesktop desk)
603 final XEnumerationAccess compEnumAccess = desk.getComponents();
604 final XEnumeration compEnum = compEnumAccess.createEnumeration();
605 boolean res = true;
609 while (compEnum.hasMoreElements())
611 final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
613 if (closer != null)
615 closer.close(true);
619 catch (com.sun.star.util.CloseVetoException cve)
621 res = false;
623 catch (com.sun.star.container.NoSuchElementException nsee)
625 res = false;
627 catch (com.sun.star.lang.WrappedTargetException wte)
629 res = false;
632 return res;
635 public static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
637 Object xPathSubst = null;
641 xPathSubst = xMSF.createInstance(
642 "com.sun.star.util.PathSubstitution");
644 catch (com.sun.star.uno.Exception e)
646 e.printStackTrace();
649 if (xPathSubst != null)
651 return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
653 else
655 return null;
660 * converts directory without 'file:///' prefix.
661 * and System dependend file separator
662 * @param dir
663 * @return
665 public static String getDirSys(String dir)
667 String sysDir = "";
669 final int idx = dir.indexOf("file://");
671 final int idx2 = dir.indexOf("file:///");
673 // remove leading 'file://'
674 if (idx < 0)
676 sysDir = dir;
678 else
680 sysDir = dir.substring("file://".length());
683 sysDir = utils.replaceAll13(sysDir, "%20", " ");
685 // append '/' if not there (e.g. linux)
686 if (sysDir.charAt(sysDir.length() - 1) != '/')
688 sysDir += "/";
691 // remove leading '/' and replace others with '\' on windows machines
692 final String sep = System.getProperty("file.separator");
694 if (sep.equalsIgnoreCase("\\"))
696 if (!(idx2 < 0))
698 sysDir = sysDir.substring(1);
700 else
702 //network path
703 sysDir = "//" + sysDir;
705 sysDir = sysDir.replace('/', '\\');
708 return sysDir;
712 * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
713 * this function asks the office for its location and fill the
714 * <CODE>AppExecutionCommand</CODE> with valid contet.
715 * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
716 * @param msf the <CODE>MultiServiceFactory</CODE>
717 * @param param the <CODE>TestParameters</CODE>
719 private static void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
721 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
723 // get existing AppExecutionCommand if available, else empty string
724 String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
726 String connectionString;
727 if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION) == true)
729 // This is the default behaviour
730 connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
732 else
734 // is used if UsePipeConnection=false
735 connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
738 String sysBinDir = "";
742 sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
744 catch (java.lang.Exception e)
746 dbg("could not get system binary directory");
747 return;
750 // does the existing command show to the connected office?
751 if (command.indexOf(sysBinDir) == -1)
753 command = sysBinDir + System.getProperty("file.separator") + "soffice" +
754 " --norestore --accept=" + connectionString + ";urp;";
757 dbg("update AppExecutionCommand: " + command);
759 param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
762 private static void dbg(String message)
764 if (debug)
766 System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
771 private class OfficeWatcherPing extends Thread
774 private final OfficeWatcher ow;
775 private boolean bStop = false;
777 public OfficeWatcherPing(OfficeWatcher ow)
779 this.ow = ow;
782 @Override
783 public void run()
785 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
787 while (!bStop)
789 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
790 ow.ping();
793 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
794 OfficeWatcherPing.sleep(1000); // 5000
796 catch (InterruptedException ex)
798 ex.printStackTrace();
804 public void finish()
806 synchronized(this)
808 bStop = true;
809 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
811 notify();
816 private void deleteFilesAndDirector(File file)
818 File f = file;
819 if(f.isDirectory())
821 File files[] = f.listFiles();
822 for(int i = 0; i < files.length; i++)
824 deleteFilesAndDirector(files[i]);
826 f.delete();
828 else if (f.isFile())
830 f.delete();