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