1 19 20 package org.netbeans.modules.autoupdate; 21 22 import java.io.*; 23 import java.net.URLConnection ; 24 import java.text.MessageFormat ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.logging.Level ; 28 import java.util.logging.Logger ; 29 import org.netbeans.api.progress.ProgressHandle; 30 import org.netbeans.api.progress.ProgressHandleFactory; 31 import org.netbeans.updater.UpdateTracking; 32 33 import org.openide.DialogDisplayer; 34 import org.openide.util.Lookup; 35 36 import org.openide.util.NbBundle; 37 import org.openide.NotifyDescriptor; 38 import org.openide.util.RequestProcessor; 39 40 44 class Downloader extends Object { 45 46 47 DownloadProgressPanel progressDialog; 48 49 private int downloadSize; 50 51 private int totalDownloaded; 52 53 private int moduleDownloaded; 54 55 private long modulesCount; 56 57 private boolean urlDownload; 58 59 static private int TIME_TO_CONNECTION_CHECK = 20000; 60 61 62 private static final String NBM_EXTENSION = "nbm"; 64 65 private Wizard.Validator validator; 66 67 private static final Logger err = Logger.getLogger("org.netbeans.modules.autoupdate.Downloader"); 69 private static RequestProcessor.Task READ_TIMEOUT_CHECKER; 70 private static RequestProcessor.Task DOWNLOAD_TASK; 71 private static RequestProcessor AU_REQUEST_PROCESSOR = null; 72 73 private static int DOWNLOADER_IS_INIT = -1; 74 private static int DOWNLOADER_RUNNING = 0; 75 private static int DOWNLOADER_WAITING = 1; 76 private static int DOWNLOADER_CANCELED = 2; 77 private static int DOWNLOADER_STOPPED = 3; 78 private static int DOWNLOADER_FINISHED = 4; 79 private static int DOWNLOADER_VERIFIED = 5; 80 81 private int downloadStatus = DOWNLOADER_IS_INIT; 82 83 ProgressHandle partialHandle; 85 ProgressHandle overallHandle; 86 87 88 public Downloader (DownloadProgressPanel progressDialog, Wizard.Validator validator, boolean urlDownload) { 89 this.validator = validator; 90 this.progressDialog = (DownloadProgressPanel)progressDialog; 91 this.urlDownload = urlDownload; 92 } 93 94 private static RequestProcessor getAutoupdateRequestProcessor () { 95 if (AU_REQUEST_PROCESSOR == null) { 96 AU_REQUEST_PROCESSOR = new RequestProcessor ("org-netbeans-modules-autoupdate", 10, true); } 98 return AU_REQUEST_PROCESSOR; 99 } 100 101 void doDownload() { 102 if (READ_TIMEOUT_CHECKER != null) { 103 READ_TIMEOUT_CHECKER.cancel (); 104 } 105 106 assert READ_TIMEOUT_CHECKER == null || READ_TIMEOUT_CHECKER.isFinished () : "Only one READ_TIMEOUT_CHECKER can be active"; 107 108 if (DOWNLOAD_TASK != null) { 110 DOWNLOAD_TASK.cancel (); 111 DOWNLOAD_TASK = null; 112 } 113 114 assert DOWNLOAD_TASK == null || DOWNLOAD_TASK.isFinished () : "Only one DOWNLOAD_TASK can be active"; 115 116 downloadSize = getTotalDownloadSize(); 117 118 progressDialog.setPartialLabel (""); progressDialog.setOverallLabel (""); progressDialog.setExtraLabel (""); 122 Runnable task = new Runnable () { 123 public void run() { 124 125 progressDialog.setPartialLabel (getBundle( "CTL_PreparingDownload_Label")); 127 err.log(Level.FINE, 128 "Start downloading " + modulesCount + 129 " modules [" + downloadSize + "]"); 130 131 downloadAll(); 132 133 if (DOWNLOADER_STOPPED == getStatus ()) { 134 return ; 135 } 136 137 progressDialog.setExtraLabel (getBundle ("DownloadProgressPanel.jLabel1.doneText")); 139 validator.setValid( true ); 140 } 141 }; 142 143 DOWNLOAD_TASK = getAutoupdateRequestProcessor ().post( task ); 144 } 145 146 147 private int getTotalDownloadSize( ) { 148 long result = 0L; 149 modulesCount = 0; 150 151 Iterator it = Wizard.getAllModules().iterator(); 152 153 while( it.hasNext() ) { 154 ModuleUpdate mu = (ModuleUpdate)it.next(); 155 156 if ( mu.isSelected() && !mu.isDownloadOK() ) { 157 result += mu.getDownloadSize(); 158 modulesCount++; 159 } 160 } 161 return (int) result; 162 } 163 164 165 166 private void downloadAll() { 167 168 getPartialHandle (1); 170 overallHandle = getOverallHandle (downloadSize); 171 172 int currentModule = 0; 173 totalDownloaded = 0; 174 175 Iterator it = Wizard.getAllModules().iterator(); 176 177 while( it.hasNext() ) { 178 179 if (DOWNLOADER_STOPPED == getStatus ()) { 180 return; 181 } 182 183 ModuleUpdate mu = (ModuleUpdate)it.next(); 184 if ( mu.isSelected() && !mu.isDownloadOK() ) { 185 progressDialog.setPartialLabel (mu.getName () + " [" + (currentModule + 1) + "/" + modulesCount + "]"); if ( urlDownload ) { 187 if (DOWNLOADER_FINISHED == getStatus () || DOWNLOADER_IS_INIT == getStatus ()) { 188 err.log(Level.FINE, "Do download " + mu.getName()); 189 setStatus (DOWNLOADER_IS_INIT); 190 downloadModule (mu); 191 err.log(Level.FINE, 192 "Download of " + mu.getName() + 193 " ends with status " + getStatus()); 194 } else { 195 err.log(Level.FINE, 196 "Don\'t download " + mu.getName() + 197 " due to incorrect status " + getStatus()); 198 } 199 } else { 200 downloadModuleFromLocal (mu); 201 } 202 updateOverall (); 203 if (partialHandle != null && mu.isDownloadOK ()) { 204 partialHandle.finish (); 205 currentModule++; 206 } 207 } 208 } 209 210 if (DOWNLOADER_STOPPED == getStatus ()) { 211 return ; 212 } 213 214 overallHandle.progress (downloadSize); 215 overallHandle.finish (); 216 String mssgTotal = MessageFormat.format( getBundle( "FMT_DownloadedTotal" ), new Object [] { new Integer ( downloadSize / 1024 ), 218 new Integer ( downloadSize / 1024 ) } ); 219 progressDialog.setOverallLabel (mssgTotal); 220 progressDialog.setEnableStop (false); 221 222 runVerifier (); 223 } 224 225 private void runVerifier () { 226 227 err.log(Level.FINE, "Prepare SignVerifier."); 228 if (DOWNLOADER_VERIFIED == getStatus ()) { 229 err.log(Level.FINE, "Error: SignVerifier has run before."); 230 return ; 231 } 232 233 SignVerifier signVerifier = new SignVerifier (progressDialog, validator); 234 progressDialog.setExtraLabel (getBundle("DownloadProgressPanel.jLabel1.securityText")); signVerifier.doVerify(); 236 237 setStatus (DOWNLOADER_VERIFIED); 238 } 239 240 private int getStatus () { 241 return downloadStatus; 242 } 243 244 private void setStatus (int status) { 245 downloadStatus = status; 246 } 247 248 private void ioCopy (BufferedInputStream in, BufferedOutputStream out, int flen) throws IOException { 249 int c; 250 251 try { 252 253 if (DOWNLOADER_IS_INIT == getStatus ()) { 254 setStatus (DOWNLOADER_RUNNING); 255 } 256 257 while ((DOWNLOADER_RUNNING == getStatus () || DOWNLOADER_WAITING == getStatus ()) && ( c = in.read () ) != -1 ) { 258 259 if (READ_TIMEOUT_CHECKER.getDelay () == 0) { 260 READ_TIMEOUT_CHECKER.waitFinished (); 261 } else if (READ_TIMEOUT_CHECKER.getDelay () < TIME_TO_CONNECTION_CHECK) { 262 READ_TIMEOUT_CHECKER.schedule (TIME_TO_CONNECTION_CHECK * 2); 263 } 264 265 out.write( c ); 266 267 moduleDownloaded++; 268 totalDownloaded++; 269 270 if ( moduleDownloaded % 4096 == 0 ) { 271 updateOverall(); 272 partialHandle.progress (moduleDownloaded < flen ? moduleDownloaded : flen); 273 } 274 } 275 276 if (DOWNLOADER_RUNNING == getStatus ()) { 277 setStatus (DOWNLOADER_FINISHED); 278 } 279 280 } finally { 281 if (in != null) in.close(); 282 if (out != null) out.close(); 283 } 284 285 } 286 287 289 private void downloadModule (final ModuleUpdate moduleUpdate) { 290 int flen = 0; 291 292 final File destFile = getNBM( moduleUpdate ); 293 294 try { 295 296 moduleDownloaded = 0; 297 partialHandle = getPartialHandle (1); 298 299 moduleUpdate.setDownloadStarted( true ); 300 progressDialog.setEnableStop (true); 301 302 err.log(Level.FINE, 303 "Setup checker of download " + moduleUpdate.getName()); 304 READ_TIMEOUT_CHECKER = getAutoupdateRequestProcessor ().post (new Runnable () { 305 public void run () { 306 confirmConnectionFailed (moduleUpdate); 307 } 308 }, TIME_TO_CONNECTION_CHECK * 4); 309 310 err.log(Level.FINE, 311 "Try to estabilish a conncetion to " + 312 moduleUpdate.getDistribution()); 313 progressDialog.setExtraLabel (getBundle ("DownloadProgressPanel.jLabel1.Establish")); 315 URLConnection distrConnection = moduleUpdate.getDistribution().openConnection(); 316 moduleUpdate.setRemoteDistributionFilename(distrConnection); 317 318 final BufferedInputStream bsrc = new BufferedInputStream (distrConnection.getInputStream ()); 319 BufferedOutputStream bdest = new BufferedOutputStream( new FileOutputStream( destFile ) ); 320 321 flen = distrConnection.getContentLength(); 322 if (flen == -1) { 324 flen = (int) moduleUpdate.getDownloadSize (); 325 } 326 assert flen > 0 : "Content of distrConnection of update " + moduleUpdate.getName () + " must be known and more then 0, but was " + flen; 327 partialHandle = getPartialHandle (flen); 328 progressDialog.setExtraLabel (getBundle ("DownloadProgressPanel.jLabel1.downloadText")); 330 try { 331 332 ioCopy (bsrc, bdest, flen); 333 334 if (DOWNLOADER_FINISHED == getStatus ()) { 335 moduleUpdate.setDownloadOK (true); 336 err.log(Level.FINE, 337 moduleUpdate.getName() + 338 " was downloaded correctly."); 339 } else { 340 moduleUpdate.setDownloadOK (false); 341 err.log(Level.FINE, 342 moduleUpdate.getName() + 343 " wasn\'t download correctly."); 344 moduleUpdate.setSecurity (SignVerifier.BAD_DOWNLOAD); 345 } 346 347 moduleUpdate.setDownloadStarted (false); 348 READ_TIMEOUT_CHECKER.cancel (); 349 350 } finally { 351 if (DOWNLOADER_FINISHED != getStatus ()) { 352 getNBM (moduleUpdate).delete (); 353 } 354 } 355 } catch ( IOException e ) { 356 if (DOWNLOADER_STOPPED == getStatus ()) { 357 return ; 358 } 359 360 363 validator.setValid (false); 364 365 err.log(Level.INFO, null, e); 366 367 confirmConnectionFailed (moduleUpdate); 369 } 370 371 return; 372 } 373 374 private void confirmConnectionFailed (ModuleUpdate moduleUpdate) { 375 if (DOWNLOADER_RUNNING != getStatus () && DOWNLOADER_IS_INIT != getStatus ()) { 376 return; 377 } 378 err.log(Level.FINE, 379 "Connection failed during download " + moduleUpdate.getName()); 380 setStatus (DOWNLOADER_WAITING); 381 String mssg = NbBundle.getMessage( Downloader.class, "FMT_DownloadFailed", moduleUpdate.getName() ); 383 NotifyDescriptor nd = new NotifyDescriptor.Confirmation (mssg, 384 getBundle ("CTL_DownloadFailed"), NotifyDescriptor.YES_NO_CANCEL_OPTION); 386 DialogDisplayer.getDefault().notify( nd ); 387 388 if ( nd.getValue().equals( NotifyDescriptor.CANCEL_OPTION ) ) { 389 err.log(Level.FINE, 390 "Confirm of the failed connection was canceled, continue downloading."); 391 392 setStatus (DOWNLOADER_RUNNING); 394 395 moduleUpdate.setDownloadStarted (true); 396 moduleUpdate.setSecurity (SignVerifier.BAD_DOWNLOAD); 397 if (READ_TIMEOUT_CHECKER != null) { 398 READ_TIMEOUT_CHECKER.cancel (); 399 READ_TIMEOUT_CHECKER.schedule (TIME_TO_CONNECTION_CHECK * 2); 400 } 401 validator.setValid (false); 402 return ; 403 } else if (nd.getValue ().equals (NotifyDescriptor.NO_OPTION)) { 404 err.log(Level.FINE, 405 "Interrupt download of " + moduleUpdate.getName()); 406 validator.setValid (true); 407 setStatus (DOWNLOADER_CANCELED); 408 moduleUpdate.setDownloadOK (false); 409 moduleUpdate.setDownloadStarted (false); 410 progressDialog.setExtraLabel (getBundle ("DownloadProgressPanel.jLabel1.Broken")); moduleUpdate.setSecurity (SignVerifier.BAD_DOWNLOAD); 412 413 416 DOWNLOAD_TASK.cancel (); 417 READ_TIMEOUT_CHECKER.cancel (); 418 419 runVerifier (); 420 421 return ; 422 } 423 424 READ_TIMEOUT_CHECKER.cancel (); 425 DOWNLOAD_TASK.cancel (); 426 setStatus (DOWNLOADER_STOPPED); 427 428 430 moduleUpdate.setDownloadStarted (false); 431 err.log(Level.FINE, 432 "Failed connection was confirmed, start download " + 433 moduleUpdate.getName() + " again."); 434 progressDialog.setExtraLabel (getBundle ("DownloadProgressPanel.jLabel1.Restart")); RequestProcessor.getDefault ().post (new Runnable () { 436 public void run () { 437 new Downloader (progressDialog, validator, urlDownload).doDownload (); 438 } 439 }, 100); 440 441 return ; 442 } 443 444 private void downloadModuleFromLocal (ModuleUpdate moduleUpdate) { 445 partialHandle = getPartialHandle (1); 446 if (downloadFromLocal (moduleUpdate)) { 447 totalDownloaded += moduleUpdate.getDownloadSize(); 448 } 449 updateOverall(); 450 } 451 452 private void updateOverall() { 453 String mssgTotal = NbBundle.getMessage( Downloader.class, "FMT_DownloadedTotal", new Object [] { new Integer ( (int)(totalDownloaded / 1024) ), 455 new Integer ( (int)(downloadSize / 1024) ) } ); 456 457 overallHandle.progress (downloadSize > totalDownloaded ? totalDownloaded : downloadSize); 459 progressDialog.setOverallLabel (mssgTotal); 460 } 461 462 private ProgressHandle getPartialHandle (int units) { 463 assert units >= 0 : "Count of units " + units + " must be positive."; 464 assert progressDialog != null; 465 ProgressHandle handle = ProgressHandleFactory.createHandle (getBundle ("DownloadProgressPanel_partialHandle_name")); handle.setInitialDelay (0); 467 progressDialog.setPartialProgressComponent (handle); 468 handle.start (units); 469 return handle; 470 } 471 472 private ProgressHandle getOverallHandle (int units) { 473 assert units >= 0 : "Count of units " + units + " must be positive."; 474 assert progressDialog != null; 475 ProgressHandle handle = ProgressHandleFactory.createHandle (getBundle ("DownloadProgressPanel_overallHandle_name")); handle.setInitialDelay (0); 477 progressDialog.setOverallProgressComponent (handle); 478 handle.start (units); 479 return handle; 480 } 481 482 485 void cancelDownload() { 486 setStatus (DOWNLOADER_STOPPED); 487 validator.setValid (false); 488 } 489 490 496 497 static boolean downloadFromLocal (ModuleUpdate moduleUpdate) { 498 if ( tryCopy( moduleUpdate.getDistributionFile(), getNBM( moduleUpdate ) ) ) { 499 moduleUpdate.setDownloadOK( true ); 500 return true; 501 } 502 else { 503 getNBM( moduleUpdate ).delete(); 504 return false; 505 } 506 } 507 508 static File getNBM( ModuleUpdate mu ) { 509 File destFile = new File( Autoupdater.Support.getDownloadDirectory (null), mu.getDistributionFilename() ); 510 return destFile; 511 } 512 513 static File getMovedNBM( ModuleUpdate mu ) { 514 File destFile = null; 515 if (mu.isToInstallDir ()) 516 destFile = Autoupdater.Support.getDownloadDirectory (mu.findInstallDirectory ()); 517 else 518 destFile = Autoupdater.Support.getDownloadDirectory (null); 519 520 return new File (destFile, mu.getDistributionFilename()); 521 } 522 523 static boolean tryMove( ModuleUpdate mu ) { 524 File toCluster = mu.findInstallDirectory(); 525 526 boolean existingCluster = false; 527 for (Iterator it = UpdateTracking.clusters(true).iterator(); it.hasNext(); ) { 528 File f = (File)it.next(); 529 if (f.equals(toCluster)) { 530 existingCluster = true; 531 break; 532 } 533 } 534 535 DO_CLUSTER: if (!existingCluster) { 536 for (Iterator it = Lookup.getDefault().lookupAll(AutoupdateClusterCreator.class).iterator(); it.hasNext(); ) { 537 AutoupdateClusterCreator a = (AutoupdateClusterCreator)it.next(); 538 539 if (toCluster.equals(a.findCluster(toCluster.getName()))) { 540 File[] allClusters; 541 try { 542 allClusters = a.registerCluster(toCluster.getName(), toCluster); 543 } catch (IOException ex) { 544 return false; 545 } 546 547 StringBuffer sb = new StringBuffer (); 548 String sep = ""; 549 for (int i = 0; i < allClusters.length; i++) { 550 sb.append(sep); 551 sb.append(allClusters[i].getPath()); 552 sep = File.pathSeparator; 553 } 554 System.setProperty("netbeans.dirs", sb.toString()); 556 break DO_CLUSTER; 557 } 558 } 559 assert false; 560 } 561 562 563 564 565 File inst = new File ( 566 Autoupdater.Support.getDownloadDirectory (mu.findInstallDirectory ()), 567 mu.getDistributionFilename() 568 ); 569 570 boolean ok = getNBM( mu ).renameTo( inst ); 571 if ( ok ) 572 return true; 573 574 ok = tryCopy( getNBM( mu ), inst ); 576 if ( ok ) 577 getNBM( mu ).delete(); 578 579 return ok; 580 } 581 582 static void saveCopy( ModuleUpdate mu, File target ) { 583 tryCopy( getNBM( mu ), target ); 584 } 585 586 private static boolean tryCopy( File src, File dest ) { 587 BufferedInputStream bsrc = null; 588 BufferedOutputStream bdest = null; 589 590 try { 591 try { 592 bsrc = new BufferedInputStream( new FileInputStream( src ), 4096 ); 593 bdest = new BufferedOutputStream( new FileOutputStream( dest ), 4096 ); 594 595 int c; 596 while( ( c = bsrc.read() ) != -1 ) { 597 bdest.write( c ); 598 } 599 } 600 finally { 601 if (bsrc != null) bsrc.close(); 603 if (bdest != null) bdest.close(); 604 } 605 } 606 catch ( IOException e ) { 607 return false; 608 } 609 return true; 610 } 611 612 static void deleteModuleNBM( ModuleUpdate mu ) { 613 getNBM( mu ).delete(); 614 } 615 616 static void deleteDownload() { 618 boolean noTestPrepared = true; 619 PreparedModules prepared = null; 620 621 List clusters = UpdateTracking.clusters (true); 622 assert clusters != null : "Clusters cannot be empty."; Iterator it = clusters.iterator (); 624 while (it.hasNext ()) { 625 if (Autoupdater.Support.getInstall_Later ((File)it.next ()).exists ()) { 626 noTestPrepared = false; 627 prepared = PreparedModules.getPrepared(); 628 } 629 } 630 631 File[] nbms = getNBMFiles(); 632 633 for( int i = 0; i < nbms.length; i++ ) { 634 if ( noTestPrepared || !prepared.hasNBM( nbms[i].getName() ) ) 635 nbms[i].delete(); 636 } 637 } 638 639 static boolean bannedWriteToInstall(ModuleUpdate mu) { 640 File f = mu.findInstallDirectory (); 641 642 return f == null || !f.canWrite(); 643 } 644 645 private static File[] getNBMFiles() { 646 File dirList[] = Autoupdater.Support.getDownloadDirectory (null).listFiles( new FilenameFilter() { 647 public boolean accept( File dir, String name ) { 648 return name.endsWith( NBM_EXTENSION ); 649 } 650 }); 651 652 return dirList; 653 } 654 655 private String getBundle( String key ) { 656 return NbBundle.getMessage( Downloader.class, key ); 657 } 658 659 } 660 | Popular Tags |