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 package helper;
28 
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;
41 
42 import java.io.File;
43 import java.io.PrintWriter;
44 import java.util.StringTokenizer;
45 
46 import lib.TestParameters;
47 
48 import share.DescEntry;
49 import share.LogWriter;
50 
51 import util.DynamicClassLoader;
52 import util.PropertyName;
53 import util.utils;
54 
55 /**
56  * This class will connect the office and start it if possible
57  *
58  */
59 public class OfficeProvider implements AppProvider
60 {
61 
62     private static boolean debug = false;
63 
64     /**
65      * copy the user layer to a safe place, usualy to $TMP/user_backup$USER
66      * @param param
67      * @param msf
68      */
69     public void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
70     {
71         try
72         {
73             final XStringSubstitution sts = createStringSubstitution(msf);
74             debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
75 
76             String userLayer = sts.getSubstituteVariableValue("$(user)");
77             userLayer = getDirSys(userLayer);
78             param.put("userLayer", userLayer);
79 
80             final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
81                     "user_backup" +
82                     System.getProperty("user.name");
83             param.put("copyLayer", copyLayer);
84 
85 
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();
90 
91             deleteFilesAndDirector (new File(copyLayer));
92             FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
93                     {
94                         "temp"
95                     });
96 
97             owp.finish();
98 
99         }
100         catch (com.sun.star.container.NoSuchElementException e)
101         {
102             System.out.println("User Variable '$(user)' not defined.");
103         }
104         catch (java.io.IOException e)
105         {
106             System.out.println("Couldn't backup user layer");
107             e.printStackTrace();
108         }
109     }
110 
111     /**
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
117      */
118     public boolean disposeManager(lib.TestParameters param)
119     {
120 
121         XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
122 
123         if (msf == null)
124         {
125             return true;
126         }
127         else
128         {
129             XDesktop desk = null;
130 
131             try
132             {
133                 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
134             }
135             catch (com.sun.star.uno.Exception ue)
136             {
137                 return false;
138             }
139 
140             msf = null;
141 
142             if (desk != null)
143             {
144                 desk.terminate();
145 
146                 return true;
147             }
148             else
149             {
150                 return false;
151             }
152         }
153     }
154 
155     /**
156      * Method to get the ServiceManager of an Office
157      * @param param
158      * @return
159      */
160     public Object getManager(lib.TestParameters param)
161     {
162         String errorMessage = null;
163         boolean bAppExecutionHasWarning = false;
164         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
165 
166         String additionalArgs = (String) param.get(
167                 "AdditionalConnectionArguments");
168 
169         if (additionalArgs == null)
170         {
171             additionalArgs = ";";
172         }
173         else
174         {
175             additionalArgs = "," + additionalArgs + ";";
176         }
177 
178         final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
179                 additionalArgs + "StarOffice.ServiceManager";
180 
181         System.out.println("Connecting the Office with " + cncstr);
182 
183         XMultiServiceFactory msf = connectOffice(cncstr);
184 
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))
191         {
192             makeAppExecCommand(msf, param);
193         }
194 
195         if (msf == null)
196         {
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("");
202 
203             if (isAppKnown)
204             {
205                 dbg("Local Connection trying to start the Office");
206 
207                 //ensure that a pending officewatcher gets finished before a new
208                 //office is started
209                 final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
210 
211                 if (ow_old != null)
212                 {
213                     ow_old.finish = true;
214                 }
215 
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"))
223                 {
224                     System.out.println(errorMessage);
225                     return null;
226                 }
227                 bAppExecutionHasWarning = !errorMessage.equals("OK");
228 
229                 final DynamicClassLoader dcl = new DynamicClassLoader();
230                 final LogWriter log = (LogWriter) dcl.getInstance(
231                         (String) param.get("LogWriter"));
232 
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;
244 
245                 log.initialize(Entry, debug);
246 
247                 final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
248                 isExecutable = ph.executeAsynchronously();
249 
250                 if (isExecutable)
251                 {
252                     param.put("AppProvider", ph);
253                     final OfficeWatcher ow = new OfficeWatcher(param);
254                     param.put("Watcher", ow);
255                     ow.start();
256                     ow.ping();
257                 }
258 
259                 int k = 0;
260 
261                 // wait up to 21 seconds to get an office connection
262                 while ((k < 42) && (msf == null))
263                 {
264                     try
265                     {
266                         msf = connect(cncstr);
267                     }
268                     catch (com.sun.star.uno.Exception ue)
269                     {
270                         exConnectFailed = ue;
271                         exc = ue.getMessage();
272                     }
273                     catch (java.lang.Exception je)
274                     {
275                         exConnectFailed = je;
276                         exc = je.getMessage();
277                     }
278                     if (msf == null)
279                     {
280                         try
281                         {
282                             Thread.sleep(k * 500);
283                         }
284                         catch (InterruptedException ex)
285                         {
286                         }
287                     }
288                     k++;
289                 }
290 
291                 if (msf == null)
292                 {
293                     System.out.println("Exception while connecting.\n" + exConnectFailed);
294                     if (exc != null)
295                     {
296                         System.out.println(exc);
297                     }
298                     if (bAppExecutionHasWarning)
299                     {
300                         System.out.println(errorMessage);
301                     }
302                 }
303                 else if (isExecutable)
304                 {
305                     if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
306                     {
307                         backupUserLayer(param, msf);
308                     }
309                 }
310             }
311             else
312             {
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)
316                 {
317                     System.out.println(errorMessage);
318                 }
319             }
320         }
321 
322         return msf;
323     }
324 
325     /**
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
333      */
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
339     {
340 
341         // Get component context
342         final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
343 
344         // initial serviceManager
345         final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
346 
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);
351 
352         final Object rInitialObject = urlResolver.resolve(connectStr);
353 
354         XMultiServiceFactory xMSF = null;
355 
356         if (rInitialObject != null)
357         {
358             // debug = true;
359             dbg("resolved url");
360 
361             xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
362         }
363 
364         return xMSF;
365     }
366 
367     /**
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
372      */
373     public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
374     {
375 
376         XMultiServiceFactory msf = (XMultiServiceFactory) param.getMSF();
377         final boolean alreadyConnected = (msf != null);
378         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
379 
380         if (alreadyConnected)
381         {
382             dbg("try to get ProcessHandler");
383 
384             final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
385 
386             if (ph != null)
387             {
388                 dbg("ProcessHandler != null");
389 
390                 disposeOffice(msf, param);
391 
392                 // dispose watcher in case it's still running.
393                 dbg("try to get OfficeWatcher");
394 
395                 final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
396 
397                 if ((ow != null) && ow.isAlive())
398                 {
399                     dbg("OfficeWatcher will be finished");
400                     ow.finish = true;
401                 }
402                 else
403                 {
404                     dbg("OfficeWatcher seems to be finished");
405                 }
406 
407                 return true;
408             }
409             else
410             {
411                 if (closeIfPossible)
412                 {
413                     return disposeOffice(msf, param);
414                 }
415             }
416         }
417         else
418         {
419             final String cncstr = "uno:" + param.get("ConnectionString") +
420                     ";urp;StarOffice.ServiceManager";
421             dbg("try to connect office");
422             msf = connectOffice(cncstr);
423 
424             if (closeIfPossible)
425             {
426                 return disposeOffice(msf, param);
427             }
428         }
429         dbg("closeExistingOffice finished");
430         return true;
431     }
432 
433     private XMultiServiceFactory connectOffice(String cncstr)
434     {
435         XMultiServiceFactory msf = null;
436         String exc = "";
437         // debug = true;
438 
439         dbg("trying to connect to " + cncstr);
440 
441         try
442         {
443             msf = connect(cncstr);
444         }
445         catch (com.sun.star.uno.Exception ue)
446         {
447             exc = ue.getMessage();
448         }
449         catch (java.lang.Exception je)
450         {
451             exc = je.getMessage();
452         }
453 
454         if (debug && exc != null && exc.length() != 0)
455         {
456             if (exc == null)
457             {
458                 exc = "";
459             }
460             dbg("Could not connect an Office. " + exc);
461         }
462 
463         return msf;
464     }
465 
466     private synchronized boolean disposeOffice(XMultiServiceFactory msf,
467             TestParameters param)
468     {
469         XDesktop desk = null;
470 
471         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
472 
473         boolean result = true;
474 
475         if (msf != null)
476         {
477 
478             // disable QuickStarter
479             try
480             {
481                 Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
482                 XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
483                 fps.setFastPropertyValue(0, false);
484             }
485             catch (com.sun.star.uno.Exception ex)
486             {
487                 dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
488             }
489 
490             try
491             {
492                 desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
493                 msf = null;
494 
495                 if (desk != null)
496                 {
497                     final boolean allClosed = closeAllWindows(desk);
498 
499                     if (!allClosed)
500                     {
501                         dbg("Couldn't close all office windows!");
502                     }
503 
504                     dbg("Trying to terminate the desktop");
505 
506                     desk.terminate();
507                     dbg("Desktop terminated");
508 
509                     try
510                     {
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);
514                     }
515                     catch (java.lang.InterruptedException e)
516                     {
517                     }
518                 }
519             }
520             catch (com.sun.star.uno.Exception ue)
521             {
522                 result = false;
523             }
524             catch (com.sun.star.lang.DisposedException ue)
525             {
526                 result = false;
527             }
528         }
529 
530         final String AppKillCommand = (String) param.get(util.PropertyName.APP_KILL_COMMAND);
531         if (AppKillCommand != null)
532         {
533             String sAppKillCommand = StringHelper.removeSurroundQuoteIfExists(AppKillCommand);
534             final StringTokenizer aKillCommandToken = new StringTokenizer(sAppKillCommand, ";");
535             while (aKillCommandToken.hasMoreTokens())
536             {
537                 final String sKillCommand = aKillCommandToken.nextToken();
538                 dbg("User defined an application to destroy the started process. Trying to execute: " + sKillCommand);
539 
540                 final ProcessHandler pHdl = new ProcessHandler(sKillCommand, 1000); // 3000 seems to be too long
541                 pHdl.runCommand();
542 
543                 pHdl.kill();
544             }
545         }
546 
547         final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
548 
549         if (ph != null)
550         {
551             // dispose watcher in case it's still running.
552             final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
553 
554             if ((ow != null) && ow.isAlive())
555             {
556                 ow.finish = true;
557             }
558 
559             ph.kill();
560         }
561 
562         param.remove("AppProvider");
563         param.remove("ServiceFactory");
564 
565         if (!param.getBool(util.PropertyName.DONT_BACKUP_USERLAYER))
566         {
567             //copy user_backup into user layer
568             try
569             {
570                 final String userLayer = (String) param.get("userLayer");
571                 final String copyLayer = (String) param.get("copyLayer");
572                 if (userLayer != null && copyLayer != null)
573                 {
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[]
578                             {
579                                 "temp"
580                             });
581                     dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
582 
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
585 
586 
587                 }
588                 else
589                 {
590                     System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
591                 }
592             }
593             catch (java.io.IOException e)
594             {
595                 dbg("Couldn't recover from backup\n" + e.getMessage());
596             }
597         }
598         return result;
599     }
600 
601     protected boolean closeAllWindows(XDesktop desk)
602     {
603         final XEnumerationAccess compEnumAccess = desk.getComponents();
604         final XEnumeration compEnum = compEnumAccess.createEnumeration();
605         boolean res = true;
606 
607         try
608         {
609             while (compEnum.hasMoreElements())
610             {
611                 final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
612 
613                 if (closer != null)
614                 {
615                     closer.close(true);
616                 }
617             }
618         }
619         catch (com.sun.star.util.CloseVetoException cve)
620         {
621             res = false;
622         }
623         catch (com.sun.star.container.NoSuchElementException nsee)
624         {
625             res = false;
626         }
627         catch (com.sun.star.lang.WrappedTargetException wte)
628         {
629             res = false;
630         }
631 
632         return res;
633     }
634 
635     public static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF)
636     {
637         Object xPathSubst = null;
638 
639         try
640         {
641             xPathSubst = xMSF.createInstance(
642                     "com.sun.star.util.PathSubstitution");
643         }
644         catch (com.sun.star.uno.Exception e)
645         {
646             e.printStackTrace();
647         }
648 
649         if (xPathSubst != null)
650         {
651             return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
652         }
653         else
654         {
655             return null;
656         }
657     }
658 
659     /**
660      * converts directory without 'file:///' prefix.
661      * and System dependend file separator
662      * @param dir
663      * @return
664      */
665     public static String getDirSys(String dir)
666     {
667         String sysDir = "";
668 
669         final int idx = dir.indexOf("file://");
670 
671         final int idx2 = dir.indexOf("file:///");
672 
673         // remove leading 'file://'
674         if (idx < 0)
675         {
676             sysDir = dir;
677         }
678         else
679         {
680             sysDir = dir.substring("file://".length());
681         }
682 
683         sysDir = utils.replaceAll13(sysDir, "%20", " ");
684 
685         // append '/' if not there (e.g. linux)
686         if (sysDir.charAt(sysDir.length() - 1) != '/')
687         {
688             sysDir += "/";
689         }
690 
691         // remove leading '/' and replace others with '\' on windows machines
692         final String sep = System.getProperty("file.separator");
693 
694         if (sep.equalsIgnoreCase("\\"))
695         {
696             if (!(idx2 < 0))
697             {
698                 sysDir = sysDir.substring(1);
699             }
700             else
701             {
702                 //network path
703                 sysDir = "//" + sysDir;
704             }
705             sysDir = sysDir.replace('/', '\\');
706         }
707 
708         return sysDir;
709     }
710 
711     /**
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>
718      */
719     private static void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
720     {
721         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
722 
723         // get existing AppExecutionCommand if available, else empty string
724         String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
725 
726         String connectionString;
727         if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION) == true)
728         {
729             // This is the default behaviour
730             connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
731         }
732         else
733         {
734             // is used if UsePipeConnection=false
735             connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
736         }
737 
738         String sysBinDir = "";
739 
740         try
741         {
742             sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
743         }
744         catch (java.lang.Exception e)
745         {
746             dbg("could not get system binary directory");
747             return;
748         }
749 
750         // does the existing command show to the connected office?
751         if (command.indexOf(sysBinDir) == -1)
752         {
753             command = sysBinDir + System.getProperty("file.separator") + "soffice" +
754                     " -norestore -accept=" + connectionString + ";urp;";
755         }
756 
757         dbg("update AppExecutionCommand: " + command);
758 
759         param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
760     }
761 
762     private static void dbg(String message)
763     {
764         if (debug)
765         {
766             System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
767         }
768 
769     }
770 
771     private class OfficeWatcherPing extends Thread
772     {
773 
774         private final OfficeWatcher ow;
775         private boolean bStop = false;
776 
777         public OfficeWatcherPing(OfficeWatcher ow)
778         {
779             this.ow = ow;
780         }
781 
782         @Override
783         public void run()
784         {
785             System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
786 
787             while (!bStop)
788             {
789                 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
790                 ow.ping();
791                 try
792                 {
793                     System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
794                     OfficeWatcherPing.sleep(1000); // 5000
795                 }
796                 catch (InterruptedException ex)
797                 {
798                     ex.printStackTrace();
799                 }
800             }
801 
802         }
803 
804         public void finish()
805         {
806             synchronized(this)
807             {
808                 bStop = true;
809                 System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
810 
811                 notify();
812             }
813         }
814     }
815 
816 private void deleteFilesAndDirector(File file)
817         {
818             File f = file;
819             if(f.isDirectory())
820             {
821                 File files[] = f.listFiles();
822                 for(int i = 0; i < files.length; i++)
823                 {
824                     deleteFilesAndDirector(files[i]);
825                 }
826                 f.delete();
827             }
828             else if (f.isFile())
829             {
830                 f.delete();
831             }
832         }
833 }
834