1 19 package org.netbeans.modules.ruby.rubyproject.gems; 20 21 import java.awt.Cursor ; 22 import java.awt.Dialog ; 23 import java.awt.event.ActionEvent ; 24 import java.awt.event.ActionListener ; 25 import java.io.BufferedReader ; 26 import java.io.File ; 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.InputStreamReader ; 30 import java.util.ArrayList ; 31 import java.util.Collections ; 32 import java.util.List ; 33 import java.util.Map ; 34 import javax.swing.JButton ; 35 import javax.swing.JComponent ; 36 import javax.swing.JTextArea ; 37 import org.netbeans.api.progress.ProgressHandle; 38 import org.netbeans.modules.ruby.rubyproject.execution.ExecutionService; 39 import org.netbeans.modules.ruby.rubyproject.api.RubyInstallation; 40 import org.openide.DialogDescriptor; 41 import org.openide.DialogDisplayer; 42 import org.openide.ErrorManager; 43 import org.openide.util.HelpCtx; 44 import org.openide.util.NbBundle; 45 import org.openide.util.RequestProcessor; 46 import org.openide.util.Utilities; 47 48 49 56 public class GemManager { 57 58 private static List <Gem> installed; 59 60 61 private static List <Gem> available; 62 63 64 public GemManager() { 65 } 66 67 68 public List <Gem> getInstalledGems(boolean refresh, List <String > lines) { 69 if (refresh || (installed == null)) { 70 installed = new ArrayList <Gem>(40); 71 refreshList(installed, true, lines); 72 } 73 74 return installed; 75 } 76 77 public boolean haveGem() { 78 String gem = RubyInstallation.getInstance().getGem(); 79 80 if (gem == null) { 81 return false; 82 } 83 84 return new File (gem).exists(); 85 } 86 87 88 public List <Gem> getAvailableGems(List <String > lines) { 89 if ((available == null) || (available.size() == 0)) { 90 available = new ArrayList <Gem>(300); 91 refreshList(available, false, lines); 92 } 93 94 return available; 95 } 96 97 private void refreshList(final List <Gem> list, final boolean local, final List <String > lines) { 98 list.clear(); 99 100 List <String > argList = new ArrayList <String >(); 102 103 if (local) { 104 argList.add("--local"); } else { 106 argList.add("--remote"); } 108 109 String [] args = (String [])argList.toArray(new String [argList.size()]); 110 boolean ok = gemRunner("list", null, false, null, null, null, null, null, lines, args); 111 112 if (ok) { 113 parseGemList(lines, list, local); 114 115 Collections.sort(list); 117 } 118 } 119 120 private void parseGemList(List <String > lines, List <Gem> gemList, boolean setVersion) { 121 Gem gem = null; 122 boolean listStarted = false; 123 124 for (String line : lines) { 125 if (line.length() == 0) { 126 gem = null; 127 128 continue; 129 } 130 131 if (line.startsWith("*** ")) { 132 listStarted = true; 133 gem = null; 134 135 continue; 136 } 137 138 if (!listStarted) { 139 continue; 141 } 142 143 if (Character.isWhitespace(line.charAt(0))) { 144 if (gem != null) { 145 String description = line.trim(); 146 147 if (gem.desc == null) { 148 gem.desc = description; 149 } else { 150 gem.desc = gem.desc + " " + description; 151 } 152 } 153 } else { 154 if (line.charAt(0) == '.') { 155 continue; 156 } 157 158 int versionIndex = line.indexOf('('); 160 161 if (versionIndex != -1) { 162 String name = line.substring(0, versionIndex).trim(); 163 int endIndex = line.indexOf(')'); 164 String versions; 165 166 if (endIndex != -1) { 167 versions = line.substring(versionIndex + 1, endIndex); 168 } else { 169 versions = line.substring(versionIndex); 170 } 171 172 String version = setVersion ? versions : null; 173 gem = new Gem(name, versions, version); 174 gemList.add(gem); 175 } else { 176 gem = new Gem(line.trim(), "", null); 177 gemList.add(gem); 178 } 179 } 180 } 181 } 182 183 184 private void asynchGemRunner(final JComponent parent, final String description, 185 final String successMessage, final String failureMessage, final List <String > lines, 186 final Runnable successCompletionTask, final String command, final String ... commandArgs) { 187 final Cursor originalCursor = parent.getCursor(); 188 Cursor busy = Utilities.createProgressCursor(parent); 189 parent.setCursor(busy); 190 191 final ProgressHandle progressHandle = null; 192 final boolean interactive = true; 193 final JButton closeButton = new JButton (NbBundle.getMessage(GemManager.class, "CTL_Close")); 194 closeButton.getAccessibleContext() 195 .setAccessibleDescription(NbBundle.getMessage(GemManager.class, "AD_Close")); 196 197 Object [] options = new Object [] { closeButton, DialogDescriptor.CANCEL_OPTION }; 198 closeButton.setEnabled(false); 199 200 final GemProgressPanel progress = 201 new GemProgressPanel(NbBundle.getMessage(GemManager.class, "GemPleaseWait")); 202 DialogDescriptor descriptor = 203 new DialogDescriptor(progress, description, true, options, closeButton, 204 DialogDescriptor.DEFAULT_ALIGN, new HelpCtx(InstalledGemsPanel.class), null); descriptor.setModal(true); 206 207 final Process [] processHolder = new Process [1]; 208 final Dialog dlg = DialogDisplayer.getDefault().createDialog(descriptor); 209 210 closeButton.addActionListener(new ActionListener () { 211 public void actionPerformed(ActionEvent ev) { 212 dlg.setVisible(false); 213 dlg.dispose(); 214 parent.setCursor(originalCursor); 215 } 216 }); 217 218 Runnable runner = 219 new Runnable () { 220 public void run() { 221 try { 222 JTextArea textArea = progress.getOutputArea(); 223 boolean succeeded = 224 gemRunner(command, progressHandle, interactive, description, 225 successMessage, failureMessage, textArea, processHolder, lines, 226 commandArgs); 227 228 closeButton.setEnabled(true); 229 230 progress.done(succeeded ? successMessage : failureMessage); 231 232 if (succeeded && (successCompletionTask != null)) { 233 successCompletionTask.run(); 234 } 235 } finally { 236 parent.setCursor(originalCursor); 237 } 238 } 239 }; 240 241 RequestProcessor.getDefault().post(runner, 50); 242 243 dlg.setVisible(true); 244 245 if (descriptor.getValue() == DialogDescriptor.CANCEL_OPTION) { 246 parent.setCursor(originalCursor); 247 248 Process process = processHolder[0]; 249 250 if (process != null) { 251 process.destroy(); 252 dlg.setVisible(false); 253 dlg.dispose(); 254 } 255 } 256 } 257 258 private boolean gemRunner(String command, ProgressHandle progressHandle, boolean interactive, 259 String description, String successMessage, String failureMessage, JTextArea textArea, 260 Process [] processHolder, List <String > lines, String ... commandArgs) { 261 String gemCmd = RubyInstallation.getInstance().getGem(); 263 List <String > argList = new ArrayList <String >(); 264 265 argList.add(gemCmd); 266 argList.add(command); 267 268 for (String arg : commandArgs) { 269 argList.add(arg); 270 } 271 272 String [] args = (String [])argList.toArray(new String [argList.size()]); 273 ProcessBuilder pb = new ProcessBuilder (args); 274 pb.redirectErrorStream(); 275 276 String binPath = new File (gemCmd).getParent(); 278 ExecutionService.setupEnvironment(pb, binPath); 279 280 String proxy = getNetbeansHttpProxy(); 282 283 if (proxy != null) { 284 Map <String , String > env = pb.environment(); 295 296 if ((env.get("HTTP_PROXY") == null) && (env.get("http_proxy") == null)) { env.put("HTTP_PROXY", proxy); 298 } 299 300 } 305 306 if (lines == null) { 307 lines = new ArrayList (40); 308 } 309 310 int exitCode = -1; 311 312 try { 313 Process process = pb.start(); 314 315 if (processHolder != null) { 316 processHolder[0] = process; 317 } 318 319 InputStream is = process.getInputStream(); 320 InputStreamReader isr = new InputStreamReader (is); 321 BufferedReader br = new BufferedReader (isr); 322 String line; 323 324 try { 325 while (true) { 326 line = br.readLine(); 327 328 if (line == null) { 329 break; 330 } 331 332 if (textArea != null) { 333 textArea.append(line + "\n"); 334 } 335 336 lines.add(line); 337 } 338 } catch (IOException ioe) { 339 String message = "*** Gem Process Killed ***\n"; 343 lines.add(message); 344 345 if (textArea != null) { 346 textArea.append(message); 347 } 348 } 349 350 exitCode = process.waitFor(); 351 352 if (exitCode != 0) { 353 try { 354 is = process.getErrorStream(); 359 isr = new InputStreamReader (is); 360 br = new BufferedReader (isr); 361 362 while ((line = br.readLine()) != null) { 363 if (textArea != null) { 364 textArea.append(line + "\n"); 365 } 366 367 lines.add(line); 368 } 369 } catch (IOException ioe) { 370 String message = "*** Gem Process Killed ***\n"; 374 lines.add(message); 375 376 if (textArea != null) { 377 textArea.append(message); 378 } 379 } 380 } 381 } catch (IOException ex) { 382 ErrorManager.getDefault().notify(ex); 383 } catch (InterruptedException ex) { 384 ErrorManager.getDefault().notify(ex); 385 } 386 387 boolean succeeded = exitCode == 0; 388 389 return succeeded; 390 } 391 392 407 public boolean install(Gem[] gems, JComponent parent, ProgressHandle progressHandle, boolean rdoc, 408 boolean ri, String version, boolean includeDeps, boolean asynchronous, 409 Runnable asyncCompletionTask) { 410 List <String > argList = new ArrayList <String >(); 412 413 for (Gem gem : gems) { 414 argList.add(gem.getName()); 415 } 416 417 if (!rdoc) { 419 argList.add("--no-rdoc"); } 421 422 if (!ri) { 423 argList.add("--no-ri"); } 425 426 if (includeDeps) { 427 argList.add("--include-dependencies"); } else { 429 argList.add("--ignore-dependencies"); } 431 432 argList.add("--version"); 434 if ((version != null) && (version.length() > 0)) { 435 argList.add(version); 436 } else { 437 argList.add("> 0"); } 439 440 String [] args = (String [])argList.toArray(new String [argList.size()]); 441 442 String title = NbBundle.getMessage(GemManager.class, "Installation"); 443 String success = NbBundle.getMessage(GemManager.class, "InstallationOk"); 444 String failure = NbBundle.getMessage(GemManager.class, "InstallationFailed"); 445 String gemCmd = "install"; 447 if (asynchronous) { 448 asynchGemRunner(parent, title, success, failure, null, asyncCompletionTask, gemCmd, args); 449 450 return false; 451 } else { 452 boolean ok = 453 gemRunner(gemCmd, progressHandle, true, title, success, failure, null, null, null, 454 args); 455 456 return ok; 457 } 458 } 459 460 472 public boolean uninstall(Gem[] gems, JComponent parent, ProgressHandle progressHandle, 473 boolean asynchronous, Runnable asyncCompletionTask) { 474 List <String > argList = new ArrayList <String >(); 476 477 for (Gem gem : gems) { 478 argList.add(gem.getName()); 479 } 480 481 argList.add("--all"); argList.add("--executables"); argList.add("--ignore-dependencies"); 486 String [] args = (String [])argList.toArray(new String [argList.size()]); 487 String title = NbBundle.getMessage(GemManager.class, "Uninstallation"); 488 String success = NbBundle.getMessage(GemManager.class, "UninstallationOk"); 489 String failure = NbBundle.getMessage(GemManager.class, "UninstallationFailed"); 490 String gemCmd = "uninstall"; 492 if (asynchronous) { 493 asynchGemRunner(parent, title, success, failure, null, asyncCompletionTask, gemCmd, args); 494 495 return false; 496 } else { 497 boolean ok = 498 gemRunner(gemCmd, progressHandle, true, title, success, failure, null, null, null, 499 args); 500 501 return ok; 502 } 503 } 504 505 518 public boolean update(Gem[] gems, JComponent parent, ProgressHandle progressHandle, boolean rdoc, 519 boolean ri, boolean asynchronous, Runnable asyncCompletionTask) { 520 List <String > argList = new ArrayList <String >(); 522 523 if (gems != null) { 524 for (Gem gem : gems) { 525 argList.add(gem.getName()); 526 } 527 } 528 529 argList.add("--verbose"); 531 if (!rdoc) { 532 argList.add("--no-rdoc"); } 534 535 if (!ri) { 536 argList.add("--no-ri"); } 538 539 argList.add("--include-dependencies"); 541 String [] args = (String [])argList.toArray(new String [argList.size()]); 542 543 String title = NbBundle.getMessage(GemManager.class, "Update"); 544 String success = NbBundle.getMessage(GemManager.class, "UpdateOk"); 545 String failure = NbBundle.getMessage(GemManager.class, "UpdateFailed"); 546 String gemCmd = "update"; 548 if (asynchronous) { 549 asynchGemRunner(parent, title, success, failure, null, asyncCompletionTask, gemCmd, args); 550 551 return false; 552 } else { 553 boolean ok = 554 gemRunner(gemCmd, progressHandle, true, title, success, failure, null, null, null, 555 args); 556 557 return ok; 558 } 559 } 560 561 566 private static String getNetbeansHttpProxy() { 567 String host = System.getProperty("http.proxyHost"); 569 if (host == null) { 570 return null; 571 } 572 573 String portHttp = System.getProperty("http.proxyPort"); int port; 575 576 try { 577 port = Integer.parseInt(portHttp); 578 } catch (NumberFormatException e) { 579 port = 8080; 580 } 581 582 if (host.indexOf(':') == -1) { 584 host = "http://" + host; } 586 587 return host + ":" + port; 588 } 589 590 public static class Gem implements Comparable <Gem> { 591 private String name; 592 private String desc; 593 private String version; 594 private String availableVersions; 595 596 public Gem(String name, String versions, String version) { 597 this.name = name; 598 this.version = version; 599 this.availableVersions = versions; 600 } 601 602 public String getName() { 603 return name; 604 } 605 606 public String getVersions() { 607 return availableVersions; 608 } 609 610 public String getDescription() { 611 return desc; 612 } 613 614 public String toString() { 615 StringBuilder sb = new StringBuilder (100); 617 sb.append("<html><b>"); 618 sb.append(name); 619 sb.append("</b>"); 620 621 if (version != null) { 622 sb.append(" ("); 623 sb.append(version); 624 sb.append(") "); 625 } 626 627 if (desc != null) { 628 sb.append(": "); 629 sb.append(desc); 630 } 631 632 sb.append("</html>"); 633 634 return sb.toString(); 635 } 636 637 public int compareTo(Gem other) { 638 return name.compareTo(other.name); 639 } 640 } 641 } 642 | Popular Tags |