1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 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. 14 * 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). 20 * 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. 25 * 26 ************************************************************************/ 27 28 package complex.framework.recovery; 29 30 import com.sun.star.awt.XDialog; 31 import com.sun.star.awt.XExtendedToolkit; 32 import com.sun.star.awt.XWindow; 33 import com.sun.star.beans.NamedValue; 34 import com.sun.star.frame.XController; 35 import com.sun.star.frame.XDesktop; 36 import com.sun.star.frame.XDispatch; 37 import com.sun.star.frame.XDispatchProvider; 38 import com.sun.star.frame.XModel; 39 import com.sun.star.lang.XComponent; 40 import com.sun.star.lang.XMultiServiceFactory; 41 import com.sun.star.ucb.XSimpleFileAccess; 42 import com.sun.star.uno.UnoRuntime; 43 import com.sun.star.uno.XInterface; 44 import com.sun.star.util.URL; 45 import com.sun.star.util.XURLTransformer; 46 import helper.FileTools; 47 import helper.OfficeProvider; 48 import helper.UnoProvider; 49 import java.io.File; 50 import java.io.PrintWriter; 51 import java.util.HashMap; 52 import lib.TestParameters; 53 import share.LogWriter; 54 import util.PropertyName; 55 import util.UITools; 56 import util.utils; 57 58 /** 59 * this class supports the <CODE>RecoverTest</CODE>. You will find here some helper 60 * functions. 61 */ 62 public class RecoveryTools { 63 64 private final TestParameters param; 65 private final LogWriter log; 66 67 /** 68 * Creates new OfficeWatcher 69 * @param param the test parameter 70 * @param log a log writer 71 */ 72 public RecoveryTools(TestParameters param, LogWriter log) { 73 this.param = param; 74 this.log = log; 75 76 } 77 78 /** 79 * get the active dialog from the top of the desktop 80 * @param xToolKit xToolKit the <CODE> XExtendedToolkit</CODE> to get the dialog from the top of the desktop. 81 * @return a <CODE>XDialog</CODE> interface of the dialog 82 */ 83 public XDialog getActiveDialog( XMultiServiceFactory xMSF){ 84 XWindow xWin = getActiveWindow(xMSF); 85 return (XDialog) UnoRuntime.queryInterface(XDialog.class, xWin); 86 } 87 88 public XWindow getActiveWindow( XMultiServiceFactory xMSF){ 89 XInterface xToolKit = null; 90 try { 91 xToolKit = (XInterface) xMSF.createInstance("com.sun.star.awt.Toolkit") ; 92 } catch (com.sun.star.uno.Exception e) { 93 return null; 94 } 95 96 XExtendedToolkit tk = (XExtendedToolkit) 97 UnoRuntime.queryInterface(XExtendedToolkit.class, xToolKit); 98 Object atw = tk.getActiveTopWindow(); 99 return (XWindow) UnoRuntime.queryInterface(XWindow.class, atw); 100 } 101 102 /** 103 * After a crash the office start with a recovery diaolg. It could be that the office 104 * is connectable but not all services to get the dialog a loaded. This function 105 * tries to get the dialog until the <CODE>OfficeWatcher</CODE> kills the office. 106 * @param xToolKit the <CODE> XExtendedToolkit</CODE> to get the dialog from the top of the desktop. 107 * @return a <CODE>XDialog</CODE> interface of the dialog 108 */ 109 public XDialog getActiveDialogAfterStartup(XMultiServiceFactory xMSF){ 110 // while the office starts it takes some time to get the dialog. 111 112 // the dialog is accessible AFTER the office has recoverd all documents. 113 // This could consumes more time then the TimeOut allow. 114 int counter = 0; 115 int multi = 5; 116 int pause = param.getInt(PropertyName.SHORT_WAIT)*10; 117 int timeOut = param.getInt(PropertyName.THREAD_TIME_OUT)*5; 118 int maximum = (timeOut / pause) * multi; 119 120 XDialog oDialog = getActiveDialog(xMSF); 121 122 while (oDialog == null && (counter < maximum)){ 123 log.println("waiting until the office has recoverd... remaining " + (timeOut * multi - pause * counter)/1000 + " seconds"); 124 pause(pause); 125 oDialog = getActiveDialog(xMSF); 126 counter ++; 127 } 128 return oDialog; 129 } 130 131 /** 132 * halt the thread for some time 133 */ 134 public void pause(){ 135 pause(param.getInt(PropertyName.SHORT_WAIT)); 136 } 137 138 /** 139 * halt the thread for some time 140 */ 141 public void pause(int sleepTime){ 142 sleep(sleepTime); 143 } 144 145 private void sleep(long millis){ 146 try{ 147 Thread.sleep(millis); 148 }catch (java.lang.InterruptedException e){} 149 } 150 151 /** 152 * remove the content of the user backup folder and removes the Recovery.xcu. This 153 * was done from the Office via XSimpleFileAccess 154 * @param xMSF a <CODE>XMultiServiceFactory</CODE> to get <CODE>XSimpleFileAccess</CODE> 155 * @throws com.sun.star.io.IOException the exception was thrown if something goes wrong. 156 */ 157 public void cleanRecoveryData() 158 throws com.sun.star.io.IOException 159 { 160 try{ 161 HashMap recFiles = getRecoveryFiles(); 162 163 String recoveryFolder = (String) recFiles.get("recoveryFolder"); 164 String recoveryXCU = (String) recFiles.get("recoveryXCU"); 165 166 log.println("try to remove content of '" + recoveryFolder + "'"); 167 168 File rf = new File(recoveryFolder); 169 170 boolean success = FileTools.cleanDir(rf); 171 log.println("removed " + recoveryFolder + ": " + success); 172 173 log.println("try to remove '" + recoveryXCU + "'"); 174 175 File xcu = new File(recoveryXCU); 176 if (xcu.isFile()){ 177 success = xcu.delete(); 178 log.println("removed " + recoveryXCU + " : " + success); 179 } 180 181 } catch (Exception e){ 182 throw new com.sun.star.io.IOException("could not remove old recovery data: " + e.toString()); 183 } 184 } 185 186 public HashMap getRecoveryFiles() 187 throws com.sun.star.io.IOException 188 { 189 try{ 190 log.println("try to get UnoProvider..."); 191 UnoProvider unoProv = new UnoProvider(); 192 XMultiServiceFactory xMSF = (XMultiServiceFactory) unoProv.getManager(param); 193 194 String userPath = utils.expandMacro(xMSF, "${$ORIGIN/bootstraprc:UserInstallation}"); 195 System.out.println("userPath:'" + userPath + "'"); 196 197 if (userPath.equals(""))userPath = utils.expandMacro(xMSF, "${$ORIGIN/bootstrap.ini:UserInstallation}"); 198 System.out.println("userPath:'" + userPath + "'"); 199 200 if (userPath.equals("")) throw new com.sun.star.io.IOException("could not get user path at bootstraping"); 201 202 String recoveryFolder = utils.getSystemURL(userPath + "/user/backup"); 203 204 String recoveryXCU = utils.getSystemURL(userPath + "/user/registry/data/org/openoffice/Office/Recovery.xcu"); 205 206 HashMap recFiles = new HashMap(); 207 208 recFiles.put("recoveryFolder", recoveryFolder); 209 recFiles.put("recoveryXCU", recoveryXCU); 210 return recFiles; 211 212 } catch (Exception e){ 213 throw new com.sun.star.io.IOException("could not get recovery folder: " + e.toString()); 214 } 215 216 } 217 /** 218 * This function close the office while calling terminate on the desktop. If 219 * this failed, the <CODE>ProcessHandler</CODE> kills the process. 220 * @param xMSF the <CODE>XMultiServiceFactory</CODE> 221 * @return <CODE>TRUE</CODE> if no exception was thrown, otherwise <CODE>FALSE</CODE> 222 */ 223 public boolean closeOffice(XMultiServiceFactory xMSF) { 224 try { 225 XDesktop desk = (XDesktop) UnoRuntime.queryInterface( 226 XDesktop.class, xMSF.createInstance( 227 "com.sun.star.frame.Desktop")); 228 xMSF = null; 229 230 desk.terminate(); 231 log.println("Waiting until ProcessHandler loose the office..."); 232 233 } 234 catch (java.lang.Exception e) { 235 e.printStackTrace(); 236 return false; 237 } 238 waitForClosedOffice(); 239 return true; 240 } 241 242 /** 243 * This function waits until the office is closed. If the closing time reach 244 * the value of parameter <CODE>THREAD_TIME_OUT</CODE> the office was killed. 245 */ 246 public void waitForClosedOffice(){ 247 // check for the office process 248 helper.ProcessHandler ph = (helper.ProcessHandler) param.get("AppProvider"); 249 250 int timeOut = param.getInt(PropertyName.THREAD_TIME_OUT)*5; 251 int pause = param.getInt(PropertyName.SHORT_WAIT)*20; 252 int multi = 0; 253 while ((ph != null) && (ph.getExitCode()<0) && (pause*multi < timeOut)) { 254 log.println("waiting until the office is closed... remaining " + (timeOut - pause * multi)/1000 + " seconds"); 255 pause(pause); 256 multi ++; 257 } 258 259 // be shure that office is closed 260 if (ph != null) ph.kill(); 261 } 262 263 public void killOffice(){ 264 helper.ProcessHandler ph = (helper.ProcessHandler) param.get("AppProvider"); 265 ph.kill(); 266 } 267 268 /** 269 * The office must be started WITH restore and crashreporter functionality. 270 * Therefore the parmater '<CODE>-norestore</CODE>' and '<CODE>-nocrashreport</CODE>' 271 * was removed from the <CODE>AppExecutionCommand</CODE> parameter 272 */ 273 public void removeParametersFromAppExecutionCommand(){ 274 275 //remove some params to start office 276 String office = (String) param.get("AppExecutionCommand"); 277 String[] params = {"-norestore", "-nocrashreport"}; 278 279 for (int i = 0; i < params.length; i++){ 280 int index = office.indexOf(params[i]); 281 int length = params[i].length(); 282 if (index != -1){ 283 office = office.substring(0, index) + office.substring(index + length); 284 log.println("removed '" + params[i] + "' from AppExecutionCommand: " + office); 285 } 286 } 287 param.put("AppExecutionCommand", office); 288 log.println("connect: " + (String) param.get("AppExecutionCommand")); 289 290 } 291 292 /** 293 * This function uses accessibility to handle modal dialogs like the 294 * "Are you sure" dialog. 295 * It cklick the named button given in parameter <CODE>buttonName</CODE> 296 * @param buttonName the name of the button wich should be chlicked 297 */ 298 public void handleModalDialog(XMultiServiceFactory xMSF, String buttonName) 299 throws com.sun.star.accessibility.IllegalAccessibleComponentStateException 300 { 301 302 log.println("try to get modal Dialog..."); 303 304 pause(); 305 306 XWindow oDialog = getActiveWindow(xMSF); 307 308 if (oDialog == null) throw new com.sun.star.accessibility.IllegalAccessibleComponentStateException("could not get modal Dialog"); 309 310 311 UITools oUITools = new UITools(xMSF, oDialog); 312 oUITools.printAccessibleTree((PrintWriter) log, param.getBool(PropertyName.DEBUG_IS_ACTIVE)); 313 314 try{ 315 log.println("click ' " + buttonName + "' button.."); 316 oUITools.clickButton(buttonName); 317 } catch ( java.lang.Exception e){ 318 throw new com.sun.star.accessibility.IllegalAccessibleComponentStateException("Could not klick '"+buttonName +"' at modal dialog: " + e.toString()); 319 } 320 pause(); 321 } 322 323 public void clickThreadButton(XMultiServiceFactory xMSF, XWindow xWindow, String buttonName) 324 throws com.sun.star.accessibility.IllegalAccessibleComponentStateException 325 { 326 KlickButtonThread kbt = new KlickButtonThread(xMSF, xWindow, buttonName); 327 kbt.start(); 328 pause(param.getInt(PropertyName.SHORT_WAIT) * 10); 329 } 330 331 public void copyRecoveryData(boolean backup) 332 throws com.sun.star.io.IOException, java.io.IOException 333 { 334 HashMap recFiles = null; 335 336 try{ 337 recFiles = getRecoveryFiles(); 338 } catch ( com.sun.star.io.IOException e){ 339 throw new com.sun.star.io.IOException("Could not get recovery files: " + e.toString()); 340 } 341 342 try{ 343 String recoveryFolder = (String) recFiles.get("recoveryFolder"); 344 String recoveryXCU = (String) recFiles.get("recoveryXCU"); 345 346 File recFolder = new File(recoveryFolder); 347 File recFolderBackup = new File(recoveryFolder+".recoveryTest"); 348 349 File recXCU = new File(recoveryXCU); 350 File recXCUBackup = new File(recoveryXCU + ".recoveryTest"); 351 352 if (backup){ 353 FileTools.copyDirectory(recFolder, recFolderBackup); 354 FileTools.copyFile(recXCU, recXCUBackup); 355 } else { 356 FileTools.copyDirectory(recFolderBackup, recFolder); 357 FileTools.copyFile(recXCUBackup, recXCU); 358 359 } 360 } catch (java.io.IOException e){ 361 throw new java.io.IOException("Could not copy recovery files: " + e.toString()); 362 } 363 } 364 365 366 }