KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > update > internal > core > ErrorRecoveryLog


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.update.internal.core;
12
13 import java.io.*;
14 import java.net.*;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Collection JavaDoc;
17 import java.util.Date JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Properties JavaDoc;
20
21 import org.eclipse.core.runtime.*;
22 import org.eclipse.osgi.util.NLS;
23 import org.eclipse.update.core.*;
24 import org.eclipse.update.configurator.*;
25
26
27 /**
28  * singleton pattern.
29  * manages the error/recover log file
30  */

31 public class ErrorRecoveryLog {
32
33     public static final boolean RECOVERY_ON = false;
34
35     private static final String JavaDoc ERROR_RECOVERY_LOG = "error_recovery.log"; //$NON-NLS-1$
36
private static final String JavaDoc LOG_ENTRY_KEY = "LogEntry."; //$NON-NLS-1$
37
private static final String JavaDoc RETURN_CARRIAGE = "\r\n"; //$NON-NLS-1$
38
private static final String JavaDoc END_OF_FILE = "eof=eof"; //$NON-NLS-1$
39

40     //
41
public static final String JavaDoc START_INSTALL_LOG = "START_INSTALL_LOG"; //$NON-NLS-1$
42
public static final String JavaDoc PLUGIN_ENTRY = "PLUGIN"; //$NON-NLS-1$
43
public static final String JavaDoc FRAGMENT_ENTRY = "FRAGMENT"; //$NON-NLS-1$
44
public static final String JavaDoc BUNDLE_MANIFEST_ENTRY = "BUNDLE_MANIFEST"; //$NON-NLS-1$
45
public static final String JavaDoc BUNDLE_JAR_ENTRY = "BUNDLE"; //$NON-NLS-1$
46
public static final String JavaDoc FEATURE_ENTRY = "FEATURE"; //$NON-NLS-1$
47
public static final String JavaDoc ALL_INSTALLED = "ALL_FEATURES_INSTALLED"; //$NON-NLS-1$
48
public static final String JavaDoc RENAME_ENTRY = "RENAME"; //$NON-NLS-1$
49
public static final String JavaDoc END_INSTALL_LOG = "END_INSTALL_LOG"; //$NON-NLS-1$
50
public static final String JavaDoc START_REMOVE_LOG = "REMOVE_LOG"; //$NON-NLS-1$
51
public static final String JavaDoc END_ABOUT_REMOVE = "END_ABOUT_TO_REMOVE"; //$NON-NLS-1$
52
public static final String JavaDoc DELETE_ENTRY = "DELETE"; //$NON-NLS-1$
53
public static final String JavaDoc END_REMOVE_LOG = "END_REMOVE_LOG"; //$NON-NLS-1$
54

55     public static boolean forceRemove = false;
56
57     private static ErrorRecoveryLog inst;
58     private FileWriter out;
59     private int index;
60     private List JavaDoc paths;
61     
62     private boolean open = false;
63     private int nbOfOpen = 0;
64     
65
66     /**
67      * Constructor for ErrorRecoveryLog.
68      */

69     private ErrorRecoveryLog() {
70         super();
71     }
72
73     /**
74      * Singleton
75      */

76     public static ErrorRecoveryLog getLog() {
77         if (inst == null){
78             inst = new ErrorRecoveryLog();
79         }
80         return inst;
81     }
82
83     /**
84      * get a unique identifer for the file, ensure uniqueness up to now
85      */

86     public static String JavaDoc getLocalRandomIdentifier(String JavaDoc path) {
87         
88         if (path==null) return null;
89         
90         // verify if it will be a directory without creating the file
91
// as it doesn't exist yet
92
if (path.endsWith(File.separator) || path.endsWith("/")) //$NON-NLS-1$
93
return path;
94         File file = new File(path);
95         String JavaDoc newName =
96             UpdateManagerUtils.getLocalRandomIdentifier(file.getName(), new Date JavaDoc());
97         while (new File(newName).exists()) {
98             newName =
99                 UpdateManagerUtils.getLocalRandomIdentifier(file.getName(), new Date JavaDoc());
100         }
101         File newFile = new File(file.getParentFile(),newName);
102         return newFile.getAbsolutePath();
103     }
104
105     /**
106      * returns the log file
107      * We do not check if the file exists
108      */

109     public File getRecoveryLogFile() {
110         IPlatformConfiguration configuration =
111             ConfiguratorUtils.getCurrentPlatformConfiguration();
112         URL location = configuration.getConfigurationLocation();
113         String JavaDoc locationString = location.getFile();
114         File platformConfiguration = new File(locationString);
115         if (!platformConfiguration.isDirectory()) platformConfiguration = platformConfiguration.getParentFile();
116         return new File(platformConfiguration, ERROR_RECOVERY_LOG);
117     }
118
119
120     /**
121      * Open the log
122      */

123     public void open(String JavaDoc logEntry) throws CoreException {
124         if (open) {
125             nbOfOpen++;
126             UpdateCore.warn("Open nested Error/Recovery log #"+nbOfOpen+":"+logEntry); //$NON-NLS-1$ //$NON-NLS-2$
127
return;
128         }
129         
130         File logFile = null;
131         try {
132             logFile = getRecoveryLogFile();
133             out = new FileWriter(logFile);
134             index = 0;
135             paths=null;
136             open=true;
137             nbOfOpen=0;
138             UpdateCore.warn("Start new Error/Recovery log #"+nbOfOpen+":"+logEntry); //$NON-NLS-1$ //$NON-NLS-2$
139
} catch (IOException e) {
140             throw Utilities.newCoreException(
141                 NLS.bind(Messages.UpdateManagerUtils_UnableToLog, (new Object JavaDoc[] { logFile })),
142                 e);
143         }
144         
145         append(logEntry);
146     }
147
148     /**
149      * Append the string to the log and flush
150      */

151     public void append(String JavaDoc logEntry) throws CoreException {
152         File logFile = null;
153         try {
154             if (!open) {
155                 UpdateCore.warn("Internal Error: The Error/Recovery log is not open:"+logEntry); //$NON-NLS-1$
156
return;
157             }
158
159             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(LOG_ENTRY_KEY);
160             buffer.append(index);
161             buffer.append("="); //$NON-NLS-1$
162
buffer.append(logEntry);
163             buffer.append(RETURN_CARRIAGE);
164
165             out.write(buffer.toString());
166             out.flush();
167             index++;
168         } catch (IOException e) {
169             throw Utilities.newCoreException(
170                 NLS.bind(Messages.UpdateManagerUtils_UnableToLog, (new Object JavaDoc[] { logFile })),
171                 e);
172         }
173     }
174
175     /**
176      * Append the string to the log and flush
177      */

178     public void appendPath(String JavaDoc logEntry, String JavaDoc path) throws CoreException {
179         if (path == null)
180             return;
181         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(logEntry);
182         buffer.append(" "); //$NON-NLS-1$
183
buffer.append(path);
184         append(buffer.toString());
185         
186         addPath(path);
187     }
188
189     /**
190      * Close any open recovery log
191      */

192     public void close(String JavaDoc logEntry) throws CoreException {
193         
194         if (nbOfOpen>0){
195             UpdateCore.warn("Close nested Error/Recovery log #"+nbOfOpen+":"+logEntry); //$NON-NLS-1$ //$NON-NLS-2$
196
nbOfOpen--;
197             return;
198         }
199         
200         UpdateCore.warn("Close Error/Recovery log #"+nbOfOpen+":"+logEntry); //$NON-NLS-1$ //$NON-NLS-2$
201
append(logEntry);
202         if (out != null) {
203             try {
204                 out.write(END_OF_FILE);
205                 out.flush();
206                 out.close();
207             } catch (IOException e) { //eat the exception
208
} finally {
209                 out = null;
210                 open=false;
211             }
212         }
213     }
214
215     /**
216      * Delete the file from the file system
217      */

218     public void delete() {
219         //File logFile = getRecoveryLogFile();
220
getRecoveryLogFile();
221         //if (logFile.exists())
222
//logFile.delete();
223
}
224
225     /**
226      *
227      */

228     private void addPath(String JavaDoc path){
229         if (paths==null) paths = new ArrayList JavaDoc();
230         paths.add(path);
231     }
232     
233     /**
234      * recover an install or remove that didn't finish
235      * Delete file for an unfinished delete
236      * Delete file for an unfinshed install if not all the files were installed
237      * Rename XML files for an install if all the files were installed but not renamed
238      */

239     public IStatus recover(){
240         
241         IStatus mainStatus = createStatus(IStatus.OK,Messages.ErrorRecoveryLog_recoveringStatus,null);
242         MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),mainStatus.getMessage(),null);
243
244         //check if recovery is on
245
if (!RECOVERY_ON){
246             UpdateCore.warn("Recovering is turned off. Abort recovery"); //$NON-NLS-1$
247
return multi;
248         }
249         
250         File logFile = getRecoveryLogFile();
251         if (!logFile.exists()){
252             multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_cannotFindLogFile+logFile,null));
253             return multi;
254         }
255         
256         InputStream in = null;
257         Properties JavaDoc prop = null;
258         try {
259             in = new FileInputStream(logFile);
260             prop = new Properties JavaDoc();
261             prop.load(in);
262         } catch (IOException e){
263             UpdateCore.warn("Unable to read:"+logFile,e); //$NON-NLS-1$
264
multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noPropertyFile+logFile,e));
265             return multi;
266         } finally {
267             if (in != null)
268                 try {
269                     in.close();
270                 } catch (IOException e1) {
271                 }
272         }
273         
274         String JavaDoc eof = prop.getProperty("eof"); //$NON-NLS-1$
275
if(eof!=null && eof.equals("eof")){ //$NON-NLS-1$
276
// all is good
277
delete();
278             UpdateCore.warn("Found log file. Log file contains end-of-file. No need to process"); //$NON-NLS-1$
279
multi.add(createStatus(IStatus.OK,null,null));
280             return multi;
281         }
282         
283         String JavaDoc recovery = prop.getProperty(LOG_ENTRY_KEY+"0"); //$NON-NLS-1$
284
if (recovery==null){
285             multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noLogEntry+logFile,null));
286             return multi;
287         }
288     
289         if(recovery.equalsIgnoreCase(START_INSTALL_LOG)){
290             multi.addAll(processRecoverInstall(prop));
291             return multi;
292         }
293         
294         if(recovery.equalsIgnoreCase(START_REMOVE_LOG)){
295             multi.addAll(processRecoverRemove(prop));
296             return multi;
297         }
298
299         multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noRecoveryToExecute+logFile,null));
300         return multi;
301     }
302     
303     /*
304      * creates a Status
305      */

306     private IStatus createStatus(int statusSeverity, String JavaDoc msg, Exception JavaDoc e){
307         String JavaDoc id =
308             UpdateCore.getPlugin().getBundle().getSymbolicName();
309     
310         StringBuffer JavaDoc completeString = new StringBuffer JavaDoc(""); //$NON-NLS-1$
311
if (msg!=null)
312             completeString.append(msg);
313         if (e!=null){
314             completeString.append("\r\n["); //$NON-NLS-1$
315
completeString.append(e.toString());
316             completeString.append("]\r\n"); //$NON-NLS-1$
317
}
318         return new Status(statusSeverity, id, IStatus.OK, completeString.toString(), e);
319     }
320     
321     /*
322      *
323      */

324      private IStatus processRecoverInstall(Properties JavaDoc prop){
325         
326         IStatus mainStatus = createStatus(IStatus.OK,"",null); //$NON-NLS-1$
327
MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); //$NON-NLS-1$
328

329         Collection JavaDoc values = prop.values();
330         
331         if(values.contains(END_INSTALL_LOG)){
332             // all is good
333
delete();
334             UpdateCore.warn("Found log file. Log file contains END_INSTALL_LOG. No need to process rename"); //$NON-NLS-1$
335
multi.add(createStatus(IStatus.OK,null,null));
336             return multi;
337         }
338         
339         if (values.contains(ALL_INSTALLED) && !forceRemove){
340             // finish install by renaming
341
int index = 0;
342             boolean found = false;
343             String JavaDoc val = prop.getProperty(LOG_ENTRY_KEY+index);
344             while(val!=null && !found){
345                 if(val.equalsIgnoreCase(ALL_INSTALLED)) found = true;
346                 IStatus renameStatus = processRename(val);
347                 UpdateCore.log(renameStatus);
348                 if(renameStatus.getSeverity()!=IStatus.OK){
349                     multi.add(renameStatus);
350                 }
351                 index++;
352                 val = prop.getProperty(LOG_ENTRY_KEY+index);
353             }
354             if (val==null){
355                 UpdateCore.warn("Unable to find value for :"+LOG_ENTRY_KEY+index); //$NON-NLS-1$
356
multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_wrongLogFile+LOG_ENTRY_KEY+index,null));
357                 return multi;
358             }
359             // process recovery finished
360
delete();
361             UpdateCore.warn("Found log file. Successfully recovered by renaming. Feature is installed."); //$NON-NLS-1$
362
multi.add(createStatus(IStatus.OK,null,null));
363         } else {
364             // remove all because install did not lay out all the files
365
// or recovery is not allowed
366
int index = 0;
367             String JavaDoc val = prop.getProperty(LOG_ENTRY_KEY+index);
368             while(val!=null){
369                 IStatus removeStatus = processRemove(val);
370                 UpdateCore.log(removeStatus);
371                 if(removeStatus.getSeverity()!=IStatus.OK){
372                     multi.addAll(removeStatus);
373                 }
374                 index++;
375                 val = prop.getProperty(LOG_ENTRY_KEY+index);
376             }
377             // process recovery finished
378
delete();
379             UpdateCore.warn("Found log file. Successfully recovered by removing. Feature is removed."); //$NON-NLS-1$
380
multi.add(createStatus(IStatus.OK,null,null));
381         }
382         return multi;
383      }
384      
385      /*
386       *
387       */

388       private IStatus processRename(String JavaDoc val){
389         
390         // get the path
391
int index = -1;
392         String JavaDoc newFileName = null;
393         if (val.startsWith(PLUGIN_ENTRY)){
394             index = PLUGIN_ENTRY.length();
395             newFileName= "plugin.xml"; //$NON-NLS-1$
396
} else if (val.startsWith(BUNDLE_MANIFEST_ENTRY)){
397             index = BUNDLE_MANIFEST_ENTRY.length();
398             newFileName= "META-INF/MANIFEST.MF"; //$NON-NLS-1$
399
}else if (val.startsWith(FRAGMENT_ENTRY)){
400             index = FRAGMENT_ENTRY.length();
401             newFileName= "fragment.xml"; //$NON-NLS-1$
402
} else if (val.startsWith(FEATURE_ENTRY)){
403             index = FEATURE_ENTRY.length();
404             newFileName= "feature.xml"; //$NON-NLS-1$
405
} else if (val.startsWith(BUNDLE_JAR_ENTRY)){
406             index = BUNDLE_JAR_ENTRY.length();
407         }
408         
409         if (index==-1){
410             return createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noAction+val,null);
411         }
412         
413         String JavaDoc oldName = val.substring(index+1);
414         // oldname is com.pid/plugin#####.xml
415
// or oldname is com.pid/pid_pver.jar######.tmp
416
File oldFile = new File(oldName);
417         File newFile;
418         if(val.startsWith(BUNDLE_JAR_ENTRY)){
419             newFile = new File(oldFile.getAbsolutePath().substring(0, oldFile.getAbsolutePath().lastIndexOf(".jar")+".jar".length())); //$NON-NLS-1$ //$NON-NLS-2$
420
}else{
421             newFile = new File(oldFile.getParentFile(),newFileName);
422         }
423         if (!oldFile.exists()){
424             if (newFile.exists()){
425                 // ok the file has been renamed apparently
426
return createStatus(IStatus.OK,Messages.ErrorRecoveryLog_fileAlreadyRenamed+newFile,null);
427             } else {
428                 // the file doesn't exist, log as problem, and force the removal of the feature
429
return createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_cannotFindFile+oldFile,null);
430             }
431         }
432         
433         boolean sucess = false;
434         if (newFile.exists()) {
435             UpdateManagerUtils.removeFromFileSystem(newFile);
436             UpdateCore.warn("Removing already existing file:"+newFile); //$NON-NLS-1$
437
}
438         sucess = oldFile.renameTo(newFile);
439             
440         if(!sucess){
441             String JavaDoc msg =(Messages.ErrorRecoveryLog_oldToNew+oldFile+newFile);
442             return createStatus(IStatus.ERROR,msg,null);
443         }
444         return createStatus(IStatus.OK,Messages.ErrorRecoveryLog_renamed+oldFile+Messages.ErrorRecoveryLog_to+newFile,null);
445       }
446       
447      /*
448       *
449       */

450       private IStatus processRemove(String JavaDoc val){
451         
452         IStatus mainStatus = createStatus(IStatus.OK,"",null); //$NON-NLS-1$
453
MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); //$NON-NLS-1$
454

455         // get the path
456
int index = -1;
457         if (val.startsWith(BUNDLE_JAR_ENTRY)){
458             index = BUNDLE_JAR_ENTRY.length();
459         }
460         
461         if (index==-1){
462             return createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noAction+val,null);
463         }
464         
465         String JavaDoc oldName = val.substring(index+1);
466         File oldFile = new File(oldName);
467         if (!oldFile.exists()){
468             // the jar or directory doesn't exist, log as problem, and force the removal of the feature
469
multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_cannotFindFile+oldFile,null));
470             return multi;
471         }
472         multi.addAll(removeFromFileSystem(oldFile));
473
474         return multi;
475       }
476       
477     /**
478      * return a multi status,
479      * the children are the file that couldn't be removed
480      */

481     public IStatus removeFromFileSystem(File file) {
482         
483         IStatus mainStatus = createStatus(IStatus.OK,"",null); //$NON-NLS-1$
484
MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); //$NON-NLS-1$
485

486         if (!file.exists()){
487             multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_noFiletoRemove+file,null));
488             return multi;
489         }
490             
491         if (file.isDirectory()) {
492             String JavaDoc[] files = file.list();
493             if (files != null) // be careful since file.list() can return null
494
for (int i = 0; i < files.length; ++i){
495                     multi.addAll(removeFromFileSystem(new File(file, files[i])));
496                 }
497         }
498         
499         if (!file.delete()) {
500             String JavaDoc msg = "Unable to remove file" +file.getAbsolutePath(); //$NON-NLS-1$
501
multi.add(createStatus(IStatus.ERROR,msg,null));
502         }
503         return multi;
504     }
505     
506     /*
507      *
508      */

509      private IStatus processRecoverRemove(Properties JavaDoc prop){
510         
511         IStatus mainStatus = createStatus(IStatus.OK,"",null); //$NON-NLS-1$
512
MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); //$NON-NLS-1$
513

514         Collection JavaDoc values = prop.values();
515         
516         if(values.contains(END_REMOVE_LOG)){
517             // all is good
518
delete();
519             UpdateCore.warn("Found log file. Log file contains END_REMOVE_LOG. No need to process rename"); //$NON-NLS-1$
520
multi.add(createStatus(IStatus.OK,null,null));
521             return multi;
522         }
523         
524         if (!values.contains(END_ABOUT_REMOVE)){
525             // finish install by renaming
526
multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_removeFeature,null));
527                 return multi;
528         } else {
529             // finish install by renaming
530
int index = 0;
531             boolean found = false;
532             String JavaDoc val = prop.getProperty(LOG_ENTRY_KEY+index);
533             while(val!=null && !found){
534                 if(val.equalsIgnoreCase(END_ABOUT_REMOVE)) found = true;
535                 IStatus renameStatus = processRemove(val);
536                 UpdateCore.log(renameStatus);
537                 if(renameStatus.getSeverity()!=IStatus.OK){
538                     multi.add(renameStatus);
539                 }
540                 index++;
541                 val = prop.getProperty(LOG_ENTRY_KEY+index);
542             }
543             if (val==null){
544                 UpdateCore.warn("Unable to find value for :"+LOG_ENTRY_KEY+index); //$NON-NLS-1$
545
multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_wrongLogFile+LOG_ENTRY_KEY+index,null));
546                 return multi;
547             }
548             // process recovery finished
549
delete();
550             UpdateCore.warn("Found log file. Successfully recovered by deleting. Feature is removed."); //$NON-NLS-1$
551
multi.add(createStatus(IStatus.OK,null,null));
552         }
553         return multi;
554      }
555 }
556
Popular Tags