001/* 002 * Copyright (c) 2009-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-04-23 16:56:59 +0000 (Thu, 23 Apr 2015) $' 007 * '$Revision: 33366 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.modulemanager.gui; 031 032import java.awt.event.ActionEvent; 033import java.awt.event.ActionListener; 034import java.awt.event.ItemEvent; 035import java.awt.event.ItemListener; 036import java.io.FileNotFoundException; 037import java.io.IOException; 038import java.util.ArrayList; 039import java.util.Collections; 040import java.util.List; 041import java.util.Vector; 042 043import javax.swing.DefaultListModel; 044import javax.swing.JButton; 045import javax.swing.JCheckBox; 046import javax.swing.JLabel; 047import javax.swing.JList; 048import javax.swing.JOptionPane; 049import javax.swing.JPanel; 050import javax.swing.JScrollPane; 051import javax.swing.ListModel; 052import javax.swing.ListSelectionModel; 053import javax.swing.SwingWorker; 054 055import org.apache.tools.ant.DefaultLogger; 056import org.apache.tools.ant.Project; 057import org.jdesktop.layout.GroupLayout; 058import org.kepler.build.Run; 059import org.kepler.build.modules.CurrentSuiteTxt; 060import org.kepler.build.modules.ModulesTxt; 061import org.kepler.build.modules.RollbackTxt; 062import org.kepler.build.project.PrintError; 063import org.kepler.build.project.ProjectLocator; 064import org.kepler.configuration.ConfigurationManager; 065import org.kepler.configuration.ConfigurationManagerException; 066import org.kepler.configuration.ConfigurationProperty; 067import org.kepler.modulemanager.ModuleDownloader; 068import org.kepler.modulemanager.gui.patch.PatchChecker; 069import org.kepler.util.ShutdownNotifier; 070 071/** 072 * Created by David Welker. 073 * Date: Sep 18, 2009 074 * Time: 10:26:30 AM 075 */ 076public class AvailableModulesPanel extends JPanel 077{ 078 //Component Declarations 079 080 //- List of available released suites. 081 private JLabel suitesLabel = new JLabel("Available Suites:"); 082 private SuitesList suitesList = new SuitesList(); 083 private JScrollPane suitesListScrollPane = new JScrollPane(suitesList); 084 private String suitesLabelToolTip = "List of Available Suites"; 085 086 private JCheckBox showSuitePatchesCheckBox = new JCheckBox("Show suite patches."); 087 088 //- List of all available modules, including suites. 089 private JLabel modulesLabel = new JLabel("Available Modules: "); 090 private ModulesList modulesList = new ModulesList(); 091 private JScrollPane modulesListScrollPane = new JScrollPane(modulesList); 092 private String modulesLabelToolTip = "List of Available Modules"; 093 094 private JCheckBox showTestReleasesCheckBox = new JCheckBox("Show test releases."); 095 096 private JLabel selectedLabel = new JLabel("Selected Modules:"); 097 private JList selectedModulesList = new JList(); 098 private JScrollPane selectedModulesListScrollPane = new JScrollPane(selectedModulesList); 099 private String selectedLabelToolTip = "The following modules or suites have been selected for installation"; 100 101 // private JButton retrieveButton = new JButton("Retrieve"); 102 private JButton restartButton = new JButton("Apply and Restart"); 103 private JButton cancelButton = new JButton("Cancel"); 104 private JButton selectButton = new JButton("\u2192"); 105 private JButton unselectButton = new JButton("\u2190"); 106 private JButton upButton = new JButton("\u2191"); 107 private JButton downButton = new JButton("\u2193"); 108 109 private ModuleDownloader downloader; 110 111 private JCheckBox shouldCheckForPatchesCheckBox = new JCheckBox("Automatically check for patches on startup."); 112 private JButton checkForPatchesNowButton = new JButton("Check for Patches Now"); 113 private JButton rollbackKeplerButton = new JButton("Rollback Kepler"); 114 115 public AvailableModulesPanel() 116 { 117 super(); 118 downloader = new ModuleDownloader(); 119 ModuleDownloadProgressMonitor mdpm = new ModuleDownloadProgressMonitor(this); 120 downloader.addListener(mdpm); 121 initComponents(); 122 layoutComponents(); 123 } 124 125 private void writeModulesTxt() 126 { 127 ModulesTxt modulesTxt = ModulesTxt.instance(); 128 modulesTxt.clear(); 129 ListModel listModel = selectedModulesList.getModel(); 130 String firstModule = ((String)listModel.getElementAt(0)); 131 firstModule = ModuleManagerGuiUtil.writeStringForSuite(firstModule); 132 boolean isSingleSuite = listModel.getSize() == 1 && firstModule.startsWith("*"); 133 String newSuite = isSingleSuite ? firstModule.substring(1, firstModule.length()) : "unknown"; 134 for (int i = 0; i < listModel.getSize(); i++) 135 { 136 String moduleName = (String) listModel.getElementAt(i); 137 if( moduleName.startsWith("*") ) 138 { 139 moduleName = ModuleManagerGuiUtil.writeStringForSuite(moduleName); 140 } 141 modulesTxt.add(moduleName); 142 } 143 modulesTxt.write(); 144 CurrentSuiteTxt.delete(); 145 CurrentSuiteTxt.setName(newSuite); 146 } 147 148 private void initComponents() 149 { 150 selectedModulesList.setModel(new DefaultListModel()); 151 selectedModulesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 152 //retrieveButton.setEnabled(false); 153 restartButton.setEnabled(false); 154 cancelButton.setEnabled(false); 155 upButton.setEnabled(false); 156 downButton.setEnabled(false); 157 158 restartButton.addActionListener(new ActionListener() 159 { 160 public void actionPerformed(ActionEvent event) 161 { 162 // retrieveButton.setEnabled(false); 163 int result = JOptionPane.showConfirmDialog( 164 AvailableModulesPanel.this, 165 "Any unsaved work will be LOST. Continue?", 166 "Confirm", JOptionPane.YES_NO_OPTION); 167 if (result == JOptionPane.NO_OPTION) { 168 return; 169 } 170 171 restartButton.setEnabled(false); 172 cancelButton.setEnabled(false); 173 selectButton.setEnabled(false); 174 unselectButton.setEnabled(false); 175 upButton.setEnabled(false); 176 downButton.setEnabled(false); 177 178 final Project project = new Project(); 179 project.setBaseDir(ProjectLocator.getProjectDir()); 180 181 // NOTE: before performing sanity checks on the selected suite, 182 // all the modules must be downloaded first so that we know 183 // what modules are in the selected suite. 184 185 SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() 186 { 187 @Override 188 /** Download all the modules in the selected suite. */ 189 public Void doInBackground() throws Exception 190 { 191 DefaultLogger logger = new DefaultLogger(); 192 logger.setMessageOutputLevel(Project.MSG_INFO); 193 logger.setOutputPrintStream(System.out); 194 logger.setErrorPrintStream(System.out); 195 project.addBuildListener(logger); 196 197 ListModel listModel = selectedModulesList.getModel(); 198 List<String> moduleList = new ArrayList(); 199 for (int i = 0; i < listModel.getSize(); i++) 200 { 201 moduleList.add((String) listModel.getElementAt(i)); 202 } 203 try { 204 downloader.downloadModules(moduleList); 205 } catch (FileNotFoundException e) { 206 JOptionPane.showMessageDialog( 207 AvailableModulesPanel.this, 208 e.getMessage()); 209 return null; 210 } 211 212 return null; 213 } 214 215 @Override 216 /** Perform sanity checks before restarting with the new suite. */ 217 public void done() { 218 219 // perform sanity checks on the suite 220 try { 221 RollbackTxt.save(); 222 } catch(IOException e) { 223 PrintError.message("Error saving modules.txt to rollback file.", e); 224 _enableButtons(); 225 return; 226 } 227 writeModulesTxt(); 228 boolean restart = CurrentSuitePanel.canExit(); 229 if(!restart) { 230 RollbackTxt.load(); 231 _enableButtons(); 232 return; 233 } 234 235 //XXX call ShutdownNotifer.shutdown() before spawning new process, 236 // to avoid 2nd instance potentially interfering with quitting first. 237 // see: http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5484 238 System.out.println("AvailableModulesPanel notifying shutdown listeners " + 239 "of impending shutdown. Closing any open databases may take awhile..."); 240 ShutdownNotifier.shutdown(); 241 242 System.out.println("AvailableModulesPanel Spawning new Kepler process"); 243 244 Run run = new Run(); 245 run.setTaskName("run"); 246 run.setProject(project); 247 run.init(); 248 run.setSpawn(true); 249 run.execute(); 250 251 System.out.println("AvailableModulesPanel Ending current Kepler process"); 252 System.out.println(" NOTE: This will probably throw an exception as the current process is terminated while a new Kepler process starts. This is normal and expected."); 253 254 //TODO why call exit with error arg here? 255 System.exit(1); 256 } 257 258 /** Enable buttons that were disabled when apply and restart was pushed. */ 259 private void _enableButtons() { 260 restartButton.setEnabled(true); 261 cancelButton.setEnabled(true); 262 selectButton.setEnabled(true); 263 unselectButton.setEnabled(true); 264 upButton.setEnabled(true); 265 downButton.setEnabled(true); 266 } 267 }; 268 worker.execute(); 269 270 271 } 272 }); 273 274 selectButton.addActionListener(new ActionListener() 275 { 276 public void actionPerformed(ActionEvent e) 277 { 278 for (Object s : suitesList.getSelectedValues()) 279 { 280 String suite = (String) s; 281 ((DefaultListModel) selectedModulesList.getModel()).addElement("*" + suite); 282 suitesList.removeElement(suite); 283 } 284 285 for (Object m : modulesList.getSelectedValues()) 286 { 287 String module = (String) m; 288 ((DefaultListModel) selectedModulesList.getModel()).addElement(module); 289 ((DefaultListModel) modulesList.getModel()).removeElement(module); 290 } 291 DefaultListModel m = (DefaultListModel) selectedModulesList.getModel(); 292 if (m.getSize() > 0) 293 { 294 // retrieveButton.setEnabled(true); 295 restartButton.setEnabled(true); 296 cancelButton.setEnabled(true); 297 upButton.setEnabled(true); 298 downButton.setEnabled(true); 299 } 300 } 301 }); 302 303 unselectButton.addActionListener(new ActionListener() 304 { 305 public void actionPerformed(ActionEvent e) 306 { 307 unselect(false); 308 DefaultListModel m = (DefaultListModel) selectedModulesList.getModel(); 309 if (m.getSize() == 0) 310 { 311 // retrieveButton.setEnabled(false); 312 restartButton.setEnabled(false); 313 cancelButton.setEnabled(false); 314 upButton.setEnabled(false); 315 downButton.setEnabled(false); 316 } 317 } 318 }); 319 320 upButton.addActionListener(new ActionListener() 321 { 322 public void actionPerformed(ActionEvent e) 323 { 324 moveUp(); 325 } 326 }); 327 328 downButton.addActionListener(new ActionListener() 329 { 330 public void actionPerformed(ActionEvent e) 331 { 332 moveDown(); 333 } 334 }); 335 336 showSuitePatchesCheckBox.addActionListener(new ActionListener() 337 { 338 public void actionPerformed(ActionEvent e) 339 { 340 suitesList.setShouldShowFullList(showSuitePatchesCheckBox.isSelected()); 341 } 342 }); 343 344 showTestReleasesCheckBox.addActionListener(new ActionListener() 345 { 346 public void actionPerformed(ActionEvent e) 347 { 348 //suitesList.setShowTestReleases(showTestReleasesCheckBox.isSelected()); 349 //modulesList.setShowTestReleases(showTestReleasesCheckBox.isSelected()); 350 } 351 }); 352 353 // the Show Test Releases checkbox no longer works, so hiding until 354 // can be fixed. 355 showTestReleasesCheckBox.setVisible(false); 356 357 ConfigurationProperty mm = ConfigurationManager.getInstance().getProperty(ConfigurationManager.getModule("module-manager")); 358 final ConfigurationProperty checkForPatches = mm.getProperty("check-for-patches"); 359 boolean shouldCheckForPatches = checkForPatches.getValue().trim().equals("true") ? true : false; 360 361 shouldCheckForPatchesCheckBox.setSelected(shouldCheckForPatches); 362 363 shouldCheckForPatchesCheckBox.addItemListener(new ItemListener() 364 { 365 public void itemStateChanged(ItemEvent e) 366 { 367 try 368 { 369 checkForPatches.setValue(""+shouldCheckForPatchesCheckBox.isSelected()); 370 ConfigurationManager.getInstance().saveConfiguration(); 371 } 372 catch (ConfigurationManagerException e1) 373 { 374 e1.printStackTrace(); 375 } 376 377 378 } 379 }); 380 381 checkForPatchesNowButton.addActionListener(new ActionListener() 382 { 383 384 public void actionPerformed(ActionEvent e) 385 { 386 PatchChecker.check(true, false, true); 387 } 388 }); 389 390 rollbackKeplerButton.setEnabled(RollbackTxt.exists()); 391 rollbackKeplerButton.addActionListener(new ActionListener() 392 { 393 394 public void actionPerformed(ActionEvent e) 395 { 396 397 SwingWorker worker = new SwingWorker<Void, Void>() 398 { 399 public Void doInBackground() throws Exception 400 { 401 Project project = new Project(); 402 project.setBaseDir(ProjectLocator.getProjectDir()); 403 DefaultLogger logger = new DefaultLogger(); 404 logger.setMessageOutputLevel(Project.MSG_INFO); 405 logger.setOutputPrintStream(System.out); 406 logger.setErrorPrintStream(System.out); 407 project.addBuildListener(logger); 408 409 try { 410 downloader.downloadModules(RollbackTxt.read()); 411 } catch (FileNotFoundException e) { 412 JOptionPane.showMessageDialog( 413 AvailableModulesPanel.this, 414 e.getMessage()); 415 return null; 416 } 417 418 RollbackTxt.load(); 419 420 System.out.println("AvailableModulesPanel notifiying shutdown listeners " + 421 "of impending shutdown. Closing any open databases may take awhile..."); 422 ShutdownNotifier.shutdown(); 423 424 System.out.println("AvailableModulesPanel Spawning new Kepler process"); 425 Run run = new Run(); 426 run.setTaskName("run"); 427 run.setProject(project); 428 run.init(); 429 run.setSpawn(true); 430 run.execute(); 431 432 System.out.println("Ending current Kepler process"); 433 System.out.println(" NOTE: This will probably throw an exception as the current process is terminated while a new Kepler process starts. This is normal and expected."); 434 435 //TODO why call exit with error arg here? 436 System.exit(1); 437 438 return null; 439 } 440 }; 441 worker.execute(); 442 } 443 }); 444 445 446 } 447 448 private void unselect(boolean all) 449 { 450 if (all) 451 { 452 DefaultListModel selectedModulesListModel = (DefaultListModel) selectedModulesList.getModel(); 453 //note that size changes dynamically here, so you can't use .size() in the for loop or 454 //you will always leave one item in the list 455 int size = selectedModulesListModel.size(); 456 for (int i = 0; i < size; i++) 457 { 458 String module = (String) selectedModulesListModel.getElementAt(0); 459 if (module.startsWith("*")) 460 { 461 suitesList.addElement(module.substring(1, module.length())); 462 } 463 else 464 { 465 ((DefaultListModel) modulesList.getModel()).addElement(module); 466 ((DefaultListModel) selectedModulesList.getModel()).removeElement(module); 467 } 468 } 469 } 470 else 471 { 472 for (Object m : selectedModulesList.getSelectedValues()) 473 { 474 String module = (String) m; 475 if (module.startsWith("*")) 476 { 477 suitesList.addElement(module.substring(1, module.length())); 478 } 479 else 480 { 481 ((DefaultListModel) modulesList.getModel()).addElement(module); 482 } 483 ((DefaultListModel) selectedModulesList.getModel()).removeElement(module); 484 } 485 } 486 487 DefaultListModel suitesListModel = (DefaultListModel) suitesList.getModel(); 488 489 suitesList.sort(); 490 491 DefaultListModel modulesListModel = (DefaultListModel) modulesList.getModel(); 492 Vector sortList = new Vector(); 493 for (int i = 0; i < modulesListModel.size(); i++) 494 { 495 sortList.add(modulesListModel.getElementAt(i)); 496 } 497 modulesListModel.clear(); 498 Collections.sort(sortList); 499 for (Object o : sortList) 500 { 501 modulesListModel.addElement(o); 502 } 503 504 } 505 506 private void moveUp() 507 { 508 DefaultListModel m = (DefaultListModel) selectedModulesList.getModel(); 509 if (selectedModulesList.getSelectedIndices().length == 0) 510 { 511 return; 512 } 513 int i = selectedModulesList.getSelectedIndex(); 514 if (i == 0) 515 { 516 return; 517 } 518 m.add(i - 1, m.remove(i)); 519 selectedModulesList.setSelectedIndex(i - 1); 520 } 521 522 private void moveDown() 523 { 524 DefaultListModel m = (DefaultListModel) selectedModulesList.getModel(); 525 if (selectedModulesList.getSelectedIndices().length == 0) 526 { 527 return; 528 } 529 int i = selectedModulesList.getSelectedIndex(); 530 if (i == m.getSize() - 1) 531 { 532 return; 533 } 534 m.add(i + 1, m.remove(i)); 535 selectedModulesList.setSelectedIndex(i + 1); 536 } 537 538 private void layoutComponents() 539 { 540 JPanel buttonPanel = new JPanel(); 541 buttonPanel.add(upButton); 542 buttonPanel.add(downButton); 543 544 suitesLabel.setToolTipText(suitesLabelToolTip); 545 modulesLabel.setToolTipText(modulesLabelToolTip); 546 selectedLabel.setToolTipText(selectedLabelToolTip); 547 548 GroupLayout layout = new GroupLayout(this); 549 setLayout(layout); 550 layout.setAutocreateContainerGaps(true); 551 layout.setAutocreateGaps(true); 552 553 layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.TRAILING) 554 .add( 555 layout.createSequentialGroup().add( 556 layout.createParallelGroup().add(suitesLabel).add( 557 suitesListScrollPane).add(showSuitePatchesCheckBox).add(modulesLabel).add( 558 modulesListScrollPane).add(showTestReleasesCheckBox)).add( 559 layout.createParallelGroup().add(selectButton).add( 560 unselectButton)).add( 561 layout.createParallelGroup().add(selectedLabel).add( 562 selectedModulesListScrollPane).add( 563 layout.createSequentialGroup().add(upButton).add(downButton)) 564 .add(shouldCheckForPatchesCheckBox) 565 .add(checkForPatchesNowButton) 566 .add(rollbackKeplerButton))).add( 567 layout.createSequentialGroup().add(restartButton)));//.add(cancelButton))); 568 569 layout.setVerticalGroup(layout.createSequentialGroup().add( 570 layout.createParallelGroup(GroupLayout.CENTER).add( 571 layout.createSequentialGroup().add(suitesLabel).add( 572 suitesListScrollPane).add(showSuitePatchesCheckBox).add(10).add(modulesLabel).add( 573 modulesListScrollPane).add(showTestReleasesCheckBox)).add( 574 layout.createSequentialGroup().add(selectButton) 575 .add(unselectButton)).add( 576 layout.createSequentialGroup().add(selectedLabel).add( 577 selectedModulesListScrollPane).add( 578 layout.createParallelGroup().add(upButton).add(downButton)) 579 .add(shouldCheckForPatchesCheckBox) 580 .add(checkForPatchesNowButton) 581 .add(rollbackKeplerButton))) 582// .add( 583// 584// ) 585 .add( 586 layout.createParallelGroup().add(restartButton)//.add(cancelButton))); 587 //.add( 588 // layout.createParallelGroup().add(lblrestartMsg) 589 )); 590 } 591}