1 19 20 package org.netbeans.updater; 21 22 import java.io.*; 23 import java.util.*; 24 import java.util.jar.*; 25 26 28 34 public final class ModuleUpdater extends Thread { 35 36 37 private static final String FILE_SEPARATOR = System.getProperty ("file.separator"); 38 private static final String PATH_SEPARATOR = System.getProperty ("path.separator"); 39 40 41 private static final String UPDATE_DIR = "update"; 43 44 static final String DOWNLOAD_DIR =UPDATE_DIR + FILE_SEPARATOR + "download"; 46 47 private static final String BACKUP_DIR = UPDATE_DIR + FILE_SEPARATOR + "backup"; 49 50 private static final String NB_LIB_DIR = "lib"; 52 53 public static final String UPDATE_NETBEANS_DIR = "netbeans"; 55 56 public static final String UPDATE_JAVA_EXT_DIR = "java_ext"; 58 59 public static final String UPDATE_MAIN_DIR = "main"; 61 62 private static final String JVM_PARAMS_FILE = "main.properties"; 64 65 public static final String NBM_EXTENSION = "nbm"; 67 68 public static final String LOG_FILE_NAME = "update.log"; 70 71 public static final String LATER_FILE_NAME = "install_later.xml"; 73 public static final char SPACE = ' '; 74 public static final char QUOTE = '\"'; 75 76 private File downloadDirectory = null; 77 78 79 private Set installOnly; 80 81 private Set installFiles; 82 83 84 private volatile boolean stop = false; 85 86 private volatile boolean suspend = false; 87 88 89 private long totalLength; 90 91 private static boolean fromInstall = false; 92 93 94 public void run() { 95 try { 96 97 getDownloadDirectory(); 98 99 checkStop(); 100 101 if ( downloadDirectory == null ) { 102 endRun(); 103 } 104 105 checkStop(); 106 107 installFiles = new HashSet (); 108 Iterator it = UpdateTracking.clusters (true).iterator (); 109 while (it.hasNext ()) { 110 File cluster = (File)it.next (); 111 UpdateTracking ut = UpdateTracking.getTracking (cluster); 112 if (ut != null) { 113 installFiles.addAll (ut.getModulesToInstall ()); 114 } 115 deleteInstall_Later (cluster); 116 } 117 118 if (installOnly != null) { 119 installFiles.retainAll (installOnly); 121 } 122 123 if (installFiles.isEmpty ()) { 124 endRun(); 125 } 126 127 checkStop(); 128 129 totalLength(); 130 131 checkStop(); 132 133 unpack(); 134 135 } catch (Exception x) { 136 x.printStackTrace (); 137 } finally { 138 UpdaterFrame.getUpdaterFrame().unpackingFinished(); 139 } 140 } 141 142 private void deleteInstall_Later (File cluster) { 143 File later = new File (cluster, FILE_SEPARATOR + DOWNLOAD_DIR + FILE_SEPARATOR + LATER_FILE_NAME); 144 if ( later.exists() ) { 145 later.delete(); 146 } 147 } 148 149 150 void endRun() { 151 stop = true; 152 } 153 154 155 private void checkStop() { 156 157 if ( suspend ) 158 while ( suspend ); 159 160 if ( stop ) { 161 if (UpdaterFrame.getUpdaterFrame().isFromIDE ()) { 162 UpdaterFrame.getUpdaterFrame().unpackingFinished(); 163 } else { 164 System.exit( 0 ); 165 } 166 } 167 } 168 169 171 public void setInstallOnly (File[] files) { 172 installOnly = new HashSet (); 173 for (int i = 0; i < files.length; i++) { 174 File f = files[i]; 175 try { 176 f = f.getCanonicalFile (); 177 } catch (IOException ex) { 178 } 180 installOnly.add (f); 181 } 182 } 183 184 185 private void totalLength() { 186 totalLength = 0L; 187 188 UpdaterFrame.setLabel( Localization.getBrandedString( "CTL_PreparingUnpack" ) ); 189 UpdaterFrame.setProgressRange( 0, installFiles.size ()); 190 191 Iterator it = installFiles.iterator (); 192 for( int i = 0; i < installFiles.size (); i++ ) { 193 194 JarFile jarFile = null; 195 196 try { 197 UpdaterFrame.setProgressValue( i + 1 ); 198 199 jarFile = new JarFile( (File) it.next () ); 200 Enumeration entries = jarFile.entries(); 201 while( entries.hasMoreElements() ) { 202 JarEntry entry = (JarEntry) entries.nextElement(); 203 204 checkStop(); 205 206 if ( ( entry.getName().startsWith( UPDATE_NETBEANS_DIR ) || 207 entry.getName().startsWith( ModuleUpdater.UPDATE_JAVA_EXT_DIR ) || 208 entry.getName().startsWith( UPDATE_MAIN_DIR) ) && 209 !entry.isDirectory() ) { 210 totalLength += entry.getSize(); 211 } 212 } 213 } 214 catch ( java.io.IOException e ) { 215 } 217 finally { 218 try { 219 if ( jarFile != null ) 220 jarFile.close(); 221 } 222 catch ( java.io.IOException e ) { 223 } 226 } 227 } 228 } 229 230 231 232 233 void unpack () { 234 long bytesRead = 0L; 235 boolean hasMainClass; 236 237 239 UpdaterFrame.setLabel( "" ); UpdaterFrame.setProgressRange( 0, totalLength ); 241 242 fromInstall = true; 243 244 ArrayList allTrackings = new ArrayList (); 245 HashMap l10ns = new HashMap(); 246 247 List clusters = UpdateTracking.clusters (true); 248 Iterator clustersIterator = clusters.iterator (); 249 while (clustersIterator.hasNext ()) { 250 File cluster = (File)clustersIterator.next (); 251 UpdateTracking tracking = UpdateTracking.getTracking (cluster, false); 252 if (tracking == null) { 253 continue; 254 } 255 allTrackings.add (tracking); 256 257 HashSet nbms = new HashSet (tracking.getModulesToInstall ()); 258 nbms.retainAll (installFiles); 259 260 File[] nbmFiles = (File[])nbms.toArray (new File[0]); 261 for( int i = 0; i < nbmFiles.length; i++ ) { 262 UpdateTracking.Version version; 263 UpdateTracking.Module modtrack; 264 265 ModuleUpdate mu = null; 266 try { 267 mu = new ModuleUpdate( nbmFiles[i], fromInstall ); 268 } catch (RuntimeException re) { 269 if (nbmFiles [i].exists ()) { 270 if (! nbmFiles[i].delete ()) { 271 System.out.println("Error: File " + nbmFiles [i] + " cannot be deleted. Propably file lock on the file."); assert false : "Error: File " + nbmFiles [i] + " cannot be deleted. Propably file lock on the file."; 273 nbmFiles[i].deleteOnExit (); 274 } 275 } 276 continue; 277 } 278 assert mu != null : "Module update is not null for file: " + nbmFiles[i]; if ( mu.isL10n() ) { 280 modtrack = null; 281 version = tracking.createVersion( "0" ); l10ns.put( mu, version ); 283 } else { 284 modtrack = tracking.readModuleTracking( ! fromInstall, mu.getCodenamebase(), true ); 285 version = modtrack.addNewVersion( mu.getSpecification_version() ); 286 } 287 System.gc(); 289 290 hasMainClass = false; 291 UpdaterFrame.setLabel( Localization.getBrandedString("CTL_UnpackingFile") + " " + nbmFiles[i].getName() ); UpdaterFrame.setProgressValue( bytesRead ); 293 JarFile jarFile = null; 294 295 try { 296 jarFile = new JarFile( nbmFiles[i] ); 297 Enumeration entries = jarFile.entries(); 298 while( entries.hasMoreElements() ) { 299 JarEntry entry = (JarEntry) entries.nextElement(); 300 checkStop(); 301 if ( entry.getName().startsWith( UPDATE_NETBEANS_DIR ) ) { 302 if (! entry.isDirectory ()) { 303 String pathTo = entry.getName ().substring (UPDATE_NETBEANS_DIR.length () + 1); 304 if ( mu.isL10n() ) 306 version.addL10NFileWithCrc( pathTo, Long.toString( entry.getCrc() ), mu.getSpecification_version()); 307 else 308 version.addFileWithCrc( pathTo, Long.toString( entry.getCrc() ) ); 309 310 File destFile = new File (cluster, entry.getName ().substring (UPDATE_NETBEANS_DIR.length())); 311 if ( destFile.exists() ) { 312 File bckFile = new File( getBackupDirectory (cluster), entry.getName() ); 313 bckFile.getParentFile ().mkdirs (); 314 copyStreams( new FileInputStream( destFile ), new FileOutputStream( bckFile ), -1 ); 316 } else { 317 destFile.getParentFile ().mkdirs (); 318 } 319 bytesRead = copyStreams( jarFile.getInputStream( entry ), new FileOutputStream( destFile ), bytesRead ); 320 UpdaterFrame.setProgressValue( bytesRead ); 321 } 322 } else if ( entry.getName().startsWith( UPDATE_MAIN_DIR )&& 323 !entry.isDirectory() ) { 324 File destFile = new File (getMainDirectory (cluster), 326 entry.getName().substring(UPDATE_MAIN_DIR.length() + 1) ); 327 destFile.getParentFile ().mkdirs (); 328 hasMainClass = true; 329 bytesRead = copyStreams( jarFile.getInputStream( entry ), new FileOutputStream( destFile ), bytesRead ); 330 UpdaterFrame.setProgressValue( bytesRead ); 331 } 332 } 333 if ( hasMainClass ) { 334 MainConfig mconfig = new MainConfig (getMainDirString (cluster) + FILE_SEPARATOR + JVM_PARAMS_FILE, cluster); 335 if (mconfig.isValid()) { 336 String java_path = System.getProperty ("java.home") + FILE_SEPARATOR 337 + "bin" + FILE_SEPARATOR + "java"; java_path = quoteString( java_path ); 339 String torun = java_path + " -cp " + quoteString (getMainDirString (cluster) + mconfig.getClasspath() ) + mconfig.getCommand(); startCommand(torun); 341 342 deleteDir( getMainDirectory (cluster) ); 343 } 344 } 345 } 346 catch ( java.io.IOException e ) { 347 e.printStackTrace (); 349 } 350 finally { 351 try { 352 if ( jarFile != null ) 353 jarFile.close(); 354 } 355 catch ( java.io.IOException e ) { 356 } 359 361 if (! nbmFiles[i].delete ()) { 362 System.out.println("Error: Cannot delete " + nbmFiles [i]); assert false : "Cannot delete " + nbmFiles [i]; 364 nbmFiles [i].deleteOnExit (); 365 } 366 } 367 if (! mu.isL10n ()) { 368 modtrack.write (); 369 modtrack.writeConfigModuleXMLIfMissing (); 370 } 371 } 372 } 373 374 Iterator trakingsIter = allTrackings.iterator (); 375 while (trakingsIter.hasNext ()) { 376 UpdateTracking t = (UpdateTracking)trakingsIter.next (); 377 Iterator it = l10ns.entrySet().iterator(); 379 while ( it.hasNext() ) { 380 Map.Entry entry = (Map.Entry) it.next(); 381 ModuleUpdate mod = (ModuleUpdate) entry.getKey(); 382 UpdateTracking.Version version = (UpdateTracking.Version) entry.getValue(); 383 UpdateTracking.Module modtrack = t.readModuleTracking( 384 ! mod.isFromInstall(), 385 mod.getCodenamebase(), 386 true 387 ); 388 modtrack.addL10NVersion( version ); 389 modtrack.write(); 390 } 391 t.deleteUnusedFiles (); 392 } 393 } 394 395 396 private File getDownloadDirectory() { 397 if ( downloadDirectory == null ) { 398 downloadDirectory = new File (System.getProperty ("netbeans.user") + FILE_SEPARATOR + DOWNLOAD_DIR ); 399 403 } 404 return downloadDirectory; 405 } 406 407 private void startCommand(String torun) { 408 Runtime runtime=Runtime.getRuntime(); 409 Process proces; 410 try { 411 proces=runtime.exec(parseParameters( torun )); 412 final Process proc2 = proces; 413 new Thread () { 414 public void run() { 415 try { 416 InputStreamReader stream= new InputStreamReader (proc2.getErrorStream()); 417 BufferedReader reader= new BufferedReader(stream); 418 String vystup; 419 do { 420 vystup = reader.readLine(); 421 if (vystup!=null) 422 System.out.println(vystup); 423 } while (vystup != null); 424 } catch (Exception e) { 425 e.printStackTrace(); 426 } 427 } 428 }.start(); 429 int x=proces.waitFor(); 430 } 431 catch (Exception e){ 432 e.printStackTrace(); 433 } 434 } 435 436 437 public File getBackupDirectory (File activeCluster) { 438 File backupDirectory = new File (activeCluster, BACKUP_DIR); 440 if (! backupDirectory.isDirectory ()) { 441 backupDirectory.mkdirs(); 442 } 443 444 return backupDirectory; 445 } 446 447 448 private File getMainDirectory (File activeCluster) { 449 File mainDirectory = new File (activeCluster, FILE_SEPARATOR + UPDATE_DIR + FILE_SEPARATOR + UPDATE_MAIN_DIR); 451 if (! mainDirectory.isDirectory ()) { 452 mainDirectory.mkdirs(); 453 } 454 455 return mainDirectory; 456 } 457 458 private String getMainDirString (File activeCluster) { 459 return getMainDirectory (activeCluster).getPath (); 460 } 461 462 468 public static final String quoteString(String s) { 469 if ( s.indexOf( SPACE ) > -1 ) { 470 StringBuffer sb = new StringBuffer (s); 471 int i = 0; 472 while ( i < sb.length() ) { 473 if ( sb.charAt(i) == QUOTE ) 474 sb.deleteCharAt( i ); 475 else 476 i++; 477 } 478 sb.insert( 0, QUOTE ); 479 sb.append( QUOTE ); 480 return sb.toString(); 481 } 482 return s; 483 } 484 485 493 private long copyStreams( InputStream src, OutputStream dest, 494 long progressVal ) throws java.io.IOException { 495 496 BufferedInputStream bsrc = new BufferedInputStream( src ); 497 BufferedOutputStream bdest = new BufferedOutputStream( dest ); 498 499 int count = 0; 500 501 int c; 502 503 try { 504 while( ( c = bsrc.read() ) != -1 ) { 505 bdest.write( c ); 506 count++; 507 if ( count > 8500 ) { 508 if (progressVal >= 0) { 509 progressVal += count; 510 UpdaterFrame.setProgressValue( progressVal ); 511 } 512 513 count = 0; 514 checkStop(); 515 } 516 } 517 if (progressVal >= 0) { 520 progressVal += count; 521 } 522 } 523 finally { 524 bsrc.close(); 525 bdest.close(); 526 } 527 return progressVal; 528 529 } 530 531 532 533 private static boolean canWrite( File dir, boolean create ) { 534 if ( !dir.exists() && create ) 535 536 dir.mkdirs(); 537 538 if ( !dir.isDirectory() || !dir.canWrite() ) 539 return false; 540 541 542 543 File tmp = null; 544 545 try { 546 tmp = File.createTempFile( "test", "access", dir ); } 548 catch ( java.io.IOException e ) { 549 return false; 550 } 551 552 if ( tmp == null ) 553 return false; 554 555 boolean cw = tmp.canWrite(); 556 if (cw) 557 tmp.delete(); 558 559 return cw; 560 } 561 562 private void deleteDir(File dir) { 563 File[] files=dir.listFiles(); 564 for( int j = 0; j < files.length; j++ ) { 565 if ( files[j].isDirectory() ) { 566 deleteDir( files[j] ); 567 if (! files[j].delete()) { 568 System.out.println("Error: Cannot delete " + files [j]); assert false : "Cannot delete " + files [j]; 570 } 571 } 572 } 573 } 574 575 609 private static String [] parseParameters(String s) { 610 int NULL = 0x0; int INPARAM = 0x1; int INPARAMPENDING = 0x2; int STICK = 0x4; int STICKPENDING = 0x8; Vector params = new Vector(5,5); 616 char c; 617 618 int state = NULL; 619 StringBuffer buff = new StringBuffer (20); 620 int slength = s.length(); 621 for (int i = 0; i < slength; i++) { 622 c = s.charAt(i); 623 if (Character.isWhitespace(c)) { 624 if (state == NULL) { 625 if (buff.length () > 0) { 626 params.addElement(buff.toString()); 627 buff.setLength(0); 628 } 629 } else if (state == STICK) { 630 params.addElement(buff.toString()); 631 buff.setLength(0); 632 state = NULL; 633 } else if (state == STICKPENDING) { 634 buff.append('\\'); 635 params.addElement(buff.toString()); 636 buff.setLength(0); 637 state = NULL; 638 } else if (state == INPARAMPENDING) { 639 state = INPARAM; 640 buff.append('\\'); 641 buff.append(c); 642 } else { buff.append(c); 644 } 645 continue; 646 } 647 648 if (c == '\\') { 649 if (state == NULL) { 650 ++i; 651 if (i < slength) { 652 char cc = s.charAt(i); 653 if (cc == '"' || cc == '\\') { 654 buff.append(cc); 655 } else if (Character.isWhitespace(cc)) { 656 buff.append(c); 657 --i; 658 } else { 659 buff.append(c); 660 buff.append(cc); 661 } 662 } else { 663 buff.append('\\'); 664 break; 665 } 666 continue; 667 } else if (state == INPARAM) { 668 state = INPARAMPENDING; 669 } else if (state == INPARAMPENDING) { 670 buff.append('\\'); 671 state = INPARAM; 672 } else if (state == STICK) { 673 state = STICKPENDING; 674 } else if (state == STICKPENDING) { 675 buff.append('\\'); 676 state = STICK; 677 } 678 continue; 679 } 680 681 if (c == '"') { 682 if (state == NULL) { 683 state = INPARAM; 684 } else if (state == INPARAM) { 685 state = STICK; 686 } else if (state == STICK) { 687 state = INPARAM; 688 } else if (state == STICKPENDING) { 689 buff.append('"'); 690 state = STICK; 691 } else { buff.append('"'); 693 state = INPARAM; 694 } 695 continue; 696 } 697 698 if (state == INPARAMPENDING) { 699 buff.append('\\'); 700 state = INPARAM; 701 } else if (state == STICKPENDING) { 702 buff.append('\\'); 703 state = STICK; 704 } 705 buff.append(c); 706 } 707 if (state == INPARAM) { 709 params.addElement(buff.toString()); 710 } else if ((state & (INPARAMPENDING | STICKPENDING)) != 0) { 711 buff.append('\\'); 712 params.addElement(buff.toString()); 713 } else { if (buff.length() != 0) { 715 params.addElement(buff.toString()); 716 } 717 } 718 String [] ret = new String [params.size()]; 719 params.copyInto(ret); 720 return ret; 721 } 722 723 724 725 726 class MainConfig extends Object { 727 728 729 private final String PAR_MAIN = "mainClass"; private final String PAR_RELCP = "relativeClassPath"; private final String PAR_JVMPAR = "jvm.parameters"; private final String PAR_MAINARGS = "mainClass.arguments"; 734 735 private final String VAR_IDE_HOME = "%IDE_HOME%"; private final String VAR_IDE_USER = "%IDE_USER%"; private final String VAR_FILE_SEPARATOR = "%FS%"; private final String VAR_JAVA_HOME = "%JAVA_HOME%"; private final String VAR_ICON_ROOT = "%ICON_ROOT%"; private final String ICON_ROOT = "Forte for Java"; private final String VAR_LOGFILE = "%UPDATE_LOGFILE%"; 743 744 private String parameters = ""; private String classpath = ""; 747 748 private boolean valid = false; 749 private final File activeCluster; 750 751 public MainConfig (String spath, File activeCluster) { 752 valid = readParms(spath); 753 this.activeCluster = activeCluster; 754 } 755 756 757 public String getCommand() { 758 return parameters; 759 } 760 761 762 public String getClasspath() { 763 return classpath; 764 } 765 766 767 public boolean isValid() { 768 return valid; 769 } 770 771 772 private boolean readParms(String spath) { 773 Properties details = new Properties(); 774 FileInputStream fis = null; 775 try { 776 details.load(fis = new FileInputStream(spath)); } catch (IOException e) { 778 return false; 779 } finally { 780 if (fis != null) try { fis.close(); } catch (IOException e) { }; 781 } 782 783 String mainclass; 784 String relpath; 785 String jvmparms; 786 String mainargs; 787 788 relpath = details.getProperty(PAR_RELCP,null); 789 if (relpath != null) { 790 relpath = replaceVars( relpath ); 791 StringTokenizer token = new StringTokenizer( relpath, PATH_SEPARATOR, false ); 792 while ( token.hasMoreTokens() ) { 793 classpath = classpath + PATH_SEPARATOR + changeRelative( token.nextToken() ); 794 } 795 } 796 797 parameters = ""; 798 jvmparms = details.getProperty(PAR_JVMPAR,null); 799 if (jvmparms != null) 800 parameters = parameters + " " + jvmparms; 802 mainclass = details.getProperty(PAR_MAIN,null); 803 if (mainclass == null) 804 return false; 805 else 806 parameters = parameters + " " + mainclass; 808 mainargs = details.getProperty(PAR_MAINARGS,null); 809 if (mainargs != null) 810 parameters = parameters + " " + mainargs; 812 parameters = replaceVars( parameters ); 813 return true; 814 } 815 816 private String replaceVars(String original) { 817 original = replaceAll(original,VAR_IDE_HOME, 818 org.netbeans.updater.UpdateTracking.getPlatformDir ().getPath()); 819 original = replaceAll(original,VAR_IDE_USER, 820 org.netbeans.updater.UpdateTracking.getPlatformDir ().getPath()); 821 original = replaceAll(original,VAR_FILE_SEPARATOR, 822 ModuleUpdater.this.FILE_SEPARATOR); 823 original = replaceAll(original,VAR_JAVA_HOME, 824 System.getProperty ("java.home")); 825 return original; 826 } 827 828 private String changeRelative(String path) { 829 if ( new File( path ).isAbsolute() ) 830 return path; 831 else 832 return getMainDirString (this.activeCluster) + FILE_SEPARATOR + path; 833 } 834 835 836 837 private String replaceAll(String sin, String what, String repl) { 838 StringBuffer sb = new StringBuffer (sin); 839 int i = sb.toString().indexOf(what); 840 int len = what.length(); 841 while ( i > -1 ) { 842 sb.replace(i,i + len,repl); 843 i = sb.toString().indexOf(what,i+1); 844 } 845 846 return sb.toString(); 847 } 848 } 849 } 850 | Popular Tags |