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