merge the formfield patch from ooo-build
[ooovba.git] / qadevOOo / runner / helper / OfficeProvider.java
blob4c4e07d8e1b5dd05a336b5a616cdb0ae06e4d7c5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: OfficeProvider.java,v $
10 * $Revision: 1.22.2.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 package helper;
32 //import com.sun.star.bridge.UnoUrlResolver;
33 import com.sun.star.beans.XFastPropertySet;
34 import com.sun.star.bridge.XUnoUrlResolver;
35 import com.sun.star.container.XEnumeration;
36 import com.sun.star.container.XEnumerationAccess;
37 import com.sun.star.frame.XDesktop;
38 import com.sun.star.lang.XMultiComponentFactory;
39 import com.sun.star.lang.XMultiServiceFactory;
40 import com.sun.star.uno.UnoRuntime;
41 import com.sun.star.uno.XComponentContext;
42 import com.sun.star.util.XCloseable;
43 import com.sun.star.util.XStringSubstitution;
45 import java.io.File;
46 import java.io.PrintWriter;
47 import java.util.StringTokenizer;
49 import lib.TestParameters;
51 import share.DescEntry;
52 import share.LogWriter;
54 import util.DynamicClassLoader;
55 import util.PropertyName;
56 import util.utils;
58 /**
59 * This class will connect the office and start it if possible
62 public class OfficeProvider implements AppProvider
65 protected static boolean debug = false;
67 /**
68 * copy the user layer to a safe place, usualy to $TMP/user_backup$USER
69 * @param param
70 * @param msf
72 public void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
74 try
76 final XStringSubstitution sts = createStringSubstitution(msf);
77 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
79 String userLayer = sts.getSubstituteVariableValue("$(user)");
80 userLayer = getDirSys(userLayer);
81 param.put("userLayer", userLayer);
83 final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
84 "user_backup" +
85 System.getProperty("user.name");
86 param.put("copyLayer", copyLayer);
89 dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
90 // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
91 OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
92 owp.start();
94 deleteFilesAndDirector (new File(copyLayer));
95 FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
97 "temp"
98 });
100 owp.finish();
103 catch (com.sun.star.container.NoSuchElementException e)
105 System.out.println("User Variable '$(user)' not defined.");
107 catch (java.io.IOException e)
109 System.out.println("Couldn't backup user layer");
110 e.printStackTrace();
115 * Dispose the office.
116 * This method can only be used, if the office was connected in the first
117 * place: getManager() was called first.
118 * @param param
119 * @return return true if desktop is terminates, else false
121 public boolean disposeManager(lib.TestParameters param)
124 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
126 if (msf == null)
128 return true;
130 else
132 XDesktop desk = null;
136 desk = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,
137 msf.createInstance(
138 "com.sun.star.frame.Desktop"));
140 catch (com.sun.star.uno.Exception ue)
142 return false;
145 msf = null;
147 if (desk != null)
149 desk.terminate();
151 return true;
153 else
155 return false;
161 * Method to get the ServiceManager of an Office
162 * @param param
163 * @return
165 public Object getManager(lib.TestParameters param)
167 String errorMessage = null;
168 boolean bAppExecutionHasWarning = false;
169 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
171 String additionalArgs = (String) param.get(
172 "AdditionalConnectionArguments");
174 if (additionalArgs == null)
176 additionalArgs = ";";
178 else
180 additionalArgs = "," + additionalArgs + ";";
183 final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
184 additionalArgs + "StarOffice.ServiceManager";
186 System.out.println("Connecting the Office with " + cncstr);
188 XMultiServiceFactory msf = connectOffice(cncstr);
190 // if the office is running and the office crashes while testing it could
191 // be usesfull to restart the office if possible and continuing the tests.
192 // Example: The UNO-API-Tests in the projects will be executed by calling
193 // 'damke'. This connects to an existing office. If the office crashes
194 // it is usefull to restart the office and continuing the tests.
195 if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
197 makeAppExecCommand(msf, param);
200 if (msf == null)
202 String exc = "";
203 Exception exConnectFailed = null;
204 boolean isExecutable = false;
205 boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
206 isAppKnown &= !((String) param.get("AppExecutionCommand")).equals("");
208 if (isAppKnown)
210 dbg("Local Connection trying to start the Office");
212 //ensure that a pending officewatcher gets finished before a new
213 //office is started
214 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
216 if (ow_old != null)
218 ow_old.finish = true;
221 final String cmd = (String) param.get("AppExecutionCommand");
222 dbg("AppExecutionCommand: " + cmd);
223 // validate the AppExecutionCommand, but try it out anyway.
224 // keep the error message for later.
225 errorMessage =
226 util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
227 if (errorMessage.startsWith("Error"))
229 System.out.println(errorMessage);
230 return null;
232 bAppExecutionHasWarning = !errorMessage.equals("OK");
234 final DynamicClassLoader dcl = new DynamicClassLoader();
235 final LogWriter log = (LogWriter) dcl.getInstance(
236 (String) param.get("LogWriter"));
238 //create empty entry
239 final DescEntry Entry = new DescEntry();
240 Entry.entryName = "office";
241 Entry.longName = "office";
242 Entry.EntryType = "placebo";
243 Entry.isOptional = false;
244 Entry.isToTest = false;
245 Entry.SubEntryCount = 0;
246 Entry.hasErrorMsg = false;
247 Entry.State = "non possible";
248 Entry.UserDefinedParams = param;
250 log.initialize(Entry, debug);
252 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
253 isExecutable = ph.executeAsynchronously();
255 if (isExecutable)
257 param.put("AppProvider", ph);
258 final OfficeWatcher ow = new OfficeWatcher(param);
259 param.put("Watcher", ow);
260 ow.start();
261 ow.ping();
264 int k = 0;
266 // wait up to 21 seconds to get an office connection
267 while ((k < 42) && (msf == null))
271 msf = connect(cncstr);
273 catch (com.sun.star.uno.Exception ue)
275 exConnectFailed = ue;
276 exc = ue.getMessage();
278 catch (java.lang.Exception je)
280 exConnectFailed = je;
281 exc = je.getMessage();
283 if (msf == null)
287 Thread.sleep(k * 500);
289 catch (InterruptedException ex)
293 k++;
296 if (msf == null)
298 System.out.println("Exception while connecting.\n" + exConnectFailed);
299 if (exc != null)
301 System.out.println(exc);
303 if (bAppExecutionHasWarning)
305 System.out.println(errorMessage);
308 else if (isExecutable)
310 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
312 backupUserLayer(param, msf);
316 else
318 System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
319 concat("\nsoffice -accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
320 if (bAppExecutionHasWarning)
322 System.out.println(errorMessage);
327 return msf;
331 * Connect an Office
332 * @param connectStr
333 * @return
334 * @throws com.sun.star.uno.Exception
335 * @throws com.sun.star.uno.RuntimeException
336 * @throws com.sun.star.connection.NoConnectException
337 * @throws Exception
339 protected static XMultiServiceFactory connect(String connectStr)
340 throws com.sun.star.uno.Exception,
341 com.sun.star.uno.RuntimeException,
342 com.sun.star.connection.NoConnectException,
343 Exception
346 // Get component context
347 final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(
348 null);
350 // initial serviceManager
351 final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
353 // create a connector, so that it can contact the office
354 // XUnoUrlResolver urlResolver = UnoUrlResolver.create(xcomponentcontext);
355 final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext(
356 "com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
357 final XUnoUrlResolver urlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface(
358 XUnoUrlResolver.class, xUrlResolver);
360 final Object rInitialObject = urlResolver.resolve(connectStr);
362 XMultiServiceFactory xMSF = null;
364 if (rInitialObject != null)
366 debug = true;
367 dbg("resolved url");
369 xMSF = (XMultiServiceFactory) UnoRuntime.queryInterface(
370 XMultiServiceFactory.class, rInitialObject);
373 return xMSF;
377 * Close an office.
378 * @param param The test parameters.
379 * @param closeIfPossible If true, close even if
380 * it was running before the test
382 public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
385 XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
386 final boolean alreadyConnected = (msf != null);
387 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
389 if (alreadyConnected)
391 dbg("try to get ProcessHandler");
393 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
395 if (ph != null)
397 dbg("ProcessHandler != null");
399 disposeOffice(msf, param);
401 // dispose watcher in case it's still running.
402 dbg("try to get OfficeWatcher");
404 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
406 if ((ow != null) && ow.isAlive())
408 dbg("OfficeWatcher will be finished");
409 ow.finish = true;
411 else
413 dbg("OfficeWatcher seems to be finished");
416 return true;
418 else
420 if (closeIfPossible)
422 return disposeOffice(msf, param);
426 else
428 final String cncstr = "uno:" + param.get("ConnectionString") +
429 ";urp;StarOffice.ServiceManager";
430 dbg("try to connect office");
431 msf = connectOffice(cncstr);
433 if (closeIfPossible)
435 return disposeOffice(msf, param);
438 dbg("closeExistingOffice finished");
439 return true;
442 private XMultiServiceFactory connectOffice(String cncstr)
444 XMultiServiceFactory msf = null;
445 String exc = "";
446 debug = true;
448 dbg("trying to connect to " + cncstr);
452 msf = connect(cncstr);
454 catch (com.sun.star.uno.Exception ue)
456 exc = ue.getMessage();
458 catch (java.lang.Exception je)
460 exc = je.getMessage();
463 if (debug && exc != null && exc.length() != 0)
465 if (exc == null)
467 exc = "";
469 dbg("Could not connect an Office. " + exc);
472 return msf;
475 private synchronized boolean disposeOffice(XMultiServiceFactory msf,
476 TestParameters param)
478 XDesktop desk = null;
480 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
482 boolean result = true;
484 if (msf != null)
487 // disable QuickStarter
490 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
491 XFastPropertySet fps = (XFastPropertySet) UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
492 fps.setFastPropertyValue(0, false);
494 catch (com.sun.star.uno.Exception ex)
496 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
501 desk = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,
502 msf.createInstance(
503 "com.sun.star.frame.Desktop"));
504 msf = null;
506 if (desk != null)
508 final boolean allClosed = closeAllWindows(desk);
510 if (!allClosed)
512 dbg("Couldn't close all office windows!");
515 dbg("Trying to terminate the desktop");
517 desk.terminate();
518 dbg("Desktop terminated");
522 final int closeTime = param.getInt(util.PropertyName.OFFICE_CLOSE_TIME_OUT);
523 dbg("the Office has " + closeTime / 1000 + " seconds for closing...");
524 Thread.sleep(closeTime);
526 catch (java.lang.InterruptedException e)
531 catch (com.sun.star.uno.Exception ue)
533 result = false;
535 catch (com.sun.star.lang.DisposedException ue)
537 result = false;
541 final String AppKillCommand = (String) param.get(util.PropertyName.APP_KILL_COMMAND);
542 if (AppKillCommand != null)
544 String sAppKillCommand = StringHelper.removeSurroundQuoteIfExists(AppKillCommand);
545 final StringTokenizer aKillCommandToken = new StringTokenizer(sAppKillCommand, ";");
546 while (aKillCommandToken.hasMoreTokens())
548 final String sKillCommand = aKillCommandToken.nextToken();
549 dbg("User defined an application to destroy the started process. Trying to execute: " + sKillCommand);
551 final ProcessHandler pHdl = new ProcessHandler(sKillCommand, 1000); // 3000 seems to be too long
552 pHdl.runCommand();
554 pHdl.kill();
558 final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
560 if (ph != null)
562 // dispose watcher in case it's still running.
563 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
565 if ((ow != null) && ow.isAlive())
567 ow.finish = true;
570 ph.kill();
573 param.remove("AppProvider");
574 param.remove("ServiceFactory");
576 if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
578 //copy user_backup into user layer
581 final String userLayer = (String) param.get("userLayer");
582 final String copyLayer = (String) param.get("copyLayer");
583 if (userLayer != null && copyLayer != null)
585 deleteFilesAndDirector(new File(userLayer));
586 final File copyFile = new File(copyLayer);
587 dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
588 FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
590 "temp"
592 dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
594 // remove all user_backup folder in temp dir
595 // this is for the case the runner was killed and some old backup folder still stay in temp dir
599 else
601 System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
604 catch (java.io.IOException e)
606 dbg("Couldn't recover from backup\n" + e.getMessage());
609 return result;
612 protected boolean closeAllWindows(XDesktop desk)
614 final XEnumerationAccess compEnumAccess = desk.getComponents();
615 final XEnumeration compEnum = compEnumAccess.createEnumeration();
616 boolean res = true;
620 while (compEnum.hasMoreElements())
622 final XCloseable closer = (XCloseable) UnoRuntime.queryInterface(
623 XCloseable.class,
624 compEnum.nextElement());
626 if (closer != null)
628 closer.close(true);
632 catch (com.sun.star.util.CloseVetoException cve)
634 res = false;
636 catch (com.sun.star.container.NoSuchElementException nsee)
638 res = false;
640 catch (com.sun.star.lang.WrappedTargetException wte)
642 res = false;
645 return res;
648 public static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
650 Object xPathSubst = null;
654 xPathSubst = xMSF.createInstance(
655 "com.sun.star.util.PathSubstitution");
657 catch (com.sun.star.uno.Exception e)
659 e.printStackTrace();
662 if (xPathSubst != null)
664 return (XStringSubstitution) UnoRuntime.queryInterface(
665 XStringSubstitution.class, xPathSubst);
667 else
669 return null;
674 * converts directory without 'file:///' prefix.
675 * and System dependend file separator
676 * @param dir
677 * @return
679 public static String getDirSys(String dir)
681 String sysDir = "";
683 final int idx = dir.indexOf("file://");
685 final int idx2 = dir.indexOf("file:///");
687 // remove leading 'file://'
688 if (idx < 0)
690 sysDir = dir;
692 else
694 sysDir = dir.substring("file://".length());
697 sysDir = utils.replaceAll13(sysDir, "%20", " ");
699 // append '/' if not there (e.g. linux)
700 if (sysDir.charAt(sysDir.length() - 1) != '/')
702 sysDir += "/";
705 // remove leading '/' and replace others with '\' on windows machines
706 final String sep = System.getProperty("file.separator");
708 if (sep.equalsIgnoreCase("\\"))
710 if (!(idx2 < 0))
712 sysDir = sysDir.substring(1);
714 else
716 //network path
717 sysDir = "//" + sysDir;
719 sysDir = sysDir.replace('/', '\\');
722 return sysDir;
726 * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
727 * this function asks the office for its location and fill the
728 * <CODE>AppExecutionCommand</CODE> with valid contet.
729 * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
730 * @param msf the <CODE>MultiServiceFactory</CODE>
731 * @param param the <CODE>TestParameters</CODE>
733 private static void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
735 debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
737 // get existing AppExecutionCommand if available, else empty string
738 String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
740 String connectionString;
741 if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION) == true)
743 // This is the default behaviour
744 connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
746 else
748 // is used if UsePipeConnection=false
749 connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
752 String sysBinDir = "";
756 sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
758 catch (java.lang.Exception e)
760 dbg("could not get system binary directory");
761 return;
764 // does the existing command show to the connected office?
765 if (command.indexOf(sysBinDir) == -1)
767 command = sysBinDir + System.getProperty("file.separator") + "soffice" +
768 " -norestore -accept=" + connectionString + ";urp;";
771 dbg("update AppExecutionCommand: " + command);
773 param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
776 private static void dbg(String message)
778 if (debug)
780 System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
785 private class OfficeWatcherPing extends Thread
788 private final OfficeWatcher ow;
789 private boolean bStop = false;
791 public OfficeWatcherPing(OfficeWatcher ow)
793 this.ow = ow;
796 public void run()
798 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
800 while (!bStop)
802 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
803 ow.ping();
806 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
807 OfficeWatcherPing.sleep(1000); // 5000
809 catch (InterruptedException ex)
811 ex.printStackTrace();
817 public void finish()
819 synchronized(this)
821 bStop = true;
822 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
824 notify();
829 private void deleteFilesAndDirector(File file)
831 File f = file;
832 if(f.isDirectory())
834 File files[] = f.listFiles();
835 for(int i = 0; i < files.length; i++)
837 deleteFilesAndDirector(files[i]);
839 f.delete();
841 else if (f.isFile())
843 f.delete();