1 11 package org.eclipse.update.internal.core; 12 13 import java.io.*; 14 import java.net.*; 15 import java.util.ArrayList ; 16 import java.util.Collection ; 17 import java.util.Date ; 18 import java.util.List ; 19 import java.util.Properties ; 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 31 public class ErrorRecoveryLog { 32 33 public static final boolean RECOVERY_ON = false; 34 35 private static final String ERROR_RECOVERY_LOG = "error_recovery.log"; private static final String LOG_ENTRY_KEY = "LogEntry."; private static final String RETURN_CARRIAGE = "\r\n"; private static final String END_OF_FILE = "eof=eof"; 40 public static final String START_INSTALL_LOG = "START_INSTALL_LOG"; public static final String PLUGIN_ENTRY = "PLUGIN"; public static final String FRAGMENT_ENTRY = "FRAGMENT"; public static final String BUNDLE_MANIFEST_ENTRY = "BUNDLE_MANIFEST"; public static final String BUNDLE_JAR_ENTRY = "BUNDLE"; public static final String FEATURE_ENTRY = "FEATURE"; public static final String ALL_INSTALLED = "ALL_FEATURES_INSTALLED"; public static final String RENAME_ENTRY = "RENAME"; public static final String END_INSTALL_LOG = "END_INSTALL_LOG"; public static final String START_REMOVE_LOG = "REMOVE_LOG"; public static final String END_ABOUT_REMOVE = "END_ABOUT_TO_REMOVE"; public static final String DELETE_ENTRY = "DELETE"; public static final String END_REMOVE_LOG = "END_REMOVE_LOG"; 55 public static boolean forceRemove = false; 56 57 private static ErrorRecoveryLog inst; 58 private FileWriter out; 59 private int index; 60 private List paths; 61 62 private boolean open = false; 63 private int nbOfOpen = 0; 64 65 66 69 private ErrorRecoveryLog() { 70 super(); 71 } 72 73 76 public static ErrorRecoveryLog getLog() { 77 if (inst == null){ 78 inst = new ErrorRecoveryLog(); 79 } 80 return inst; 81 } 82 83 86 public static String getLocalRandomIdentifier(String path) { 87 88 if (path==null) return null; 89 90 if (path.endsWith(File.separator) || path.endsWith("/")) return path; 94 File file = new File(path); 95 String newName = 96 UpdateManagerUtils.getLocalRandomIdentifier(file.getName(), new Date ()); 97 while (new File(newName).exists()) { 98 newName = 99 UpdateManagerUtils.getLocalRandomIdentifier(file.getName(), new Date ()); 100 } 101 File newFile = new File(file.getParentFile(),newName); 102 return newFile.getAbsolutePath(); 103 } 104 105 109 public File getRecoveryLogFile() { 110 IPlatformConfiguration configuration = 111 ConfiguratorUtils.getCurrentPlatformConfiguration(); 112 URL location = configuration.getConfigurationLocation(); 113 String 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 123 public void open(String logEntry) throws CoreException { 124 if (open) { 125 nbOfOpen++; 126 UpdateCore.warn("Open nested Error/Recovery log #"+nbOfOpen+":"+logEntry); 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); } catch (IOException e) { 140 throw Utilities.newCoreException( 141 NLS.bind(Messages.UpdateManagerUtils_UnableToLog, (new Object [] { logFile })), 142 e); 143 } 144 145 append(logEntry); 146 } 147 148 151 public void append(String 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); return; 157 } 158 159 StringBuffer buffer = new StringBuffer (LOG_ENTRY_KEY); 160 buffer.append(index); 161 buffer.append("="); 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 [] { logFile })), 171 e); 172 } 173 } 174 175 178 public void appendPath(String logEntry, String path) throws CoreException { 179 if (path == null) 180 return; 181 StringBuffer buffer = new StringBuffer (logEntry); 182 buffer.append(" "); buffer.append(path); 184 append(buffer.toString()); 185 186 addPath(path); 187 } 188 189 192 public void close(String logEntry) throws CoreException { 193 194 if (nbOfOpen>0){ 195 UpdateCore.warn("Close nested Error/Recovery log #"+nbOfOpen+":"+logEntry); nbOfOpen--; 197 return; 198 } 199 200 UpdateCore.warn("Close Error/Recovery log #"+nbOfOpen+":"+logEntry); append(logEntry); 202 if (out != null) { 203 try { 204 out.write(END_OF_FILE); 205 out.flush(); 206 out.close(); 207 } catch (IOException e) { } finally { 209 out = null; 210 open=false; 211 } 212 } 213 } 214 215 218 public void delete() { 219 getRecoveryLogFile(); 221 } 224 225 228 private void addPath(String path){ 229 if (paths==null) paths = new ArrayList (); 230 paths.add(path); 231 } 232 233 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 if (!RECOVERY_ON){ 246 UpdateCore.warn("Recovering is turned off. Abort recovery"); 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 prop = null; 258 try { 259 in = new FileInputStream(logFile); 260 prop = new Properties (); 261 prop.load(in); 262 } catch (IOException e){ 263 UpdateCore.warn("Unable to read:"+logFile,e); 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 eof = prop.getProperty("eof"); if(eof!=null && eof.equals("eof")){ delete(); 278 UpdateCore.warn("Found log file. Log file contains end-of-file. No need to process"); multi.add(createStatus(IStatus.OK,null,null)); 280 return multi; 281 } 282 283 String recovery = prop.getProperty(LOG_ENTRY_KEY+"0"); 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 306 private IStatus createStatus(int statusSeverity, String msg, Exception e){ 307 String id = 308 UpdateCore.getPlugin().getBundle().getSymbolicName(); 309 310 StringBuffer completeString = new StringBuffer (""); if (msg!=null) 312 completeString.append(msg); 313 if (e!=null){ 314 completeString.append("\r\n["); completeString.append(e.toString()); 316 completeString.append("]\r\n"); } 318 return new Status(statusSeverity, id, IStatus.OK, completeString.toString(), e); 319 } 320 321 324 private IStatus processRecoverInstall(Properties prop){ 325 326 IStatus mainStatus = createStatus(IStatus.OK,"",null); MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); 329 Collection values = prop.values(); 330 331 if(values.contains(END_INSTALL_LOG)){ 332 delete(); 334 UpdateCore.warn("Found log file. Log file contains END_INSTALL_LOG. No need to process rename"); multi.add(createStatus(IStatus.OK,null,null)); 336 return multi; 337 } 338 339 if (values.contains(ALL_INSTALLED) && !forceRemove){ 340 int index = 0; 342 boolean found = false; 343 String 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); multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_wrongLogFile+LOG_ENTRY_KEY+index,null)); 357 return multi; 358 } 359 delete(); 361 UpdateCore.warn("Found log file. Successfully recovered by renaming. Feature is installed."); multi.add(createStatus(IStatus.OK,null,null)); 363 } else { 364 int index = 0; 367 String 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 delete(); 379 UpdateCore.warn("Found log file. Successfully recovered by removing. Feature is removed."); multi.add(createStatus(IStatus.OK,null,null)); 381 } 382 return multi; 383 } 384 385 388 private IStatus processRename(String val){ 389 390 int index = -1; 392 String newFileName = null; 393 if (val.startsWith(PLUGIN_ENTRY)){ 394 index = PLUGIN_ENTRY.length(); 395 newFileName= "plugin.xml"; } else if (val.startsWith(BUNDLE_MANIFEST_ENTRY)){ 397 index = BUNDLE_MANIFEST_ENTRY.length(); 398 newFileName= "META-INF/MANIFEST.MF"; }else if (val.startsWith(FRAGMENT_ENTRY)){ 400 index = FRAGMENT_ENTRY.length(); 401 newFileName= "fragment.xml"; } else if (val.startsWith(FEATURE_ENTRY)){ 403 index = FEATURE_ENTRY.length(); 404 newFileName= "feature.xml"; } 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 oldName = val.substring(index+1); 414 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())); }else{ 421 newFile = new File(oldFile.getParentFile(),newFileName); 422 } 423 if (!oldFile.exists()){ 424 if (newFile.exists()){ 425 return createStatus(IStatus.OK,Messages.ErrorRecoveryLog_fileAlreadyRenamed+newFile,null); 427 } else { 428 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); } 438 sucess = oldFile.renameTo(newFile); 439 440 if(!sucess){ 441 String 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 450 private IStatus processRemove(String val){ 451 452 IStatus mainStatus = createStatus(IStatus.OK,"",null); MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); 455 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 oldName = val.substring(index+1); 466 File oldFile = new File(oldName); 467 if (!oldFile.exists()){ 468 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 481 public IStatus removeFromFileSystem(File file) { 482 483 IStatus mainStatus = createStatus(IStatus.OK,"",null); MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); 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 [] files = file.list(); 493 if (files != null) 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 msg = "Unable to remove file" +file.getAbsolutePath(); multi.add(createStatus(IStatus.ERROR,msg,null)); 502 } 503 return multi; 504 } 505 506 509 private IStatus processRecoverRemove(Properties prop){ 510 511 IStatus mainStatus = createStatus(IStatus.OK,"",null); MultiStatus multi = new MultiStatus(mainStatus.getPlugin(),mainStatus.getCode(),"",null); 514 Collection values = prop.values(); 515 516 if(values.contains(END_REMOVE_LOG)){ 517 delete(); 519 UpdateCore.warn("Found log file. Log file contains END_REMOVE_LOG. No need to process rename"); multi.add(createStatus(IStatus.OK,null,null)); 521 return multi; 522 } 523 524 if (!values.contains(END_ABOUT_REMOVE)){ 525 multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_removeFeature,null)); 527 return multi; 528 } else { 529 int index = 0; 531 boolean found = false; 532 String 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); multi.add(createStatus(IStatus.ERROR,Messages.ErrorRecoveryLog_wrongLogFile+LOG_ENTRY_KEY+index,null)); 546 return multi; 547 } 548 delete(); 550 UpdateCore.warn("Found log file. Successfully recovered by deleting. Feature is removed."); multi.add(createStatus(IStatus.OK,null,null)); 552 } 553 return multi; 554 } 555 } 556 | Popular Tags |