| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.autoupdate.ui; |
| |
| import java.awt.Dialog; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.JButton; |
| import javax.swing.JComponent; |
| import javax.swing.JLabel; |
| import javax.swing.JPanel; |
| import javax.swing.JScrollPane; |
| import javax.swing.JTextArea; |
| import org.netbeans.api.autoupdate.InstallSupport; |
| import org.netbeans.api.autoupdate.OperationContainer; |
| import org.netbeans.api.autoupdate.OperationException; |
| import org.netbeans.api.autoupdate.OperationSupport; |
| import org.netbeans.api.autoupdate.OperationSupport.Restarter; |
| import org.netbeans.api.autoupdate.UpdateElement; |
| import org.netbeans.api.autoupdate.UpdateManager; |
| import org.netbeans.api.autoupdate.UpdateUnit; |
| import org.netbeans.api.autoupdate.UpdateUnitProvider; |
| import org.netbeans.api.autoupdate.UpdateUnitProviderFactory; |
| import org.netbeans.api.options.OptionsDisplayer; |
| import org.netbeans.api.progress.ProgressHandle; |
| import org.netbeans.api.progress.ProgressHandleFactory; |
| import org.netbeans.modules.autoupdate.ui.api.PluginManager; |
| import org.openide.DialogDescriptor; |
| import org.openide.DialogDisplayer; |
| import org.openide.NotifyDescriptor; |
| import org.openide.awt.Mnemonics; |
| import org.openide.util.NbBundle.Messages; |
| import org.openide.util.RequestProcessor; |
| import static org.netbeans.modules.autoupdate.ui.Bundle.*; |
| |
| /** |
| * |
| * @author Jesse Glick |
| * @author Jan Lahoda |
| * @author Petr Hejl |
| */ |
| public class ModuleInstallerSupport { |
| private static RequestProcessor RP = new RequestProcessor(ModuleInstallerSupport.class.getName(), 1); |
| private static final Logger LOG = Logger.getLogger(ModuleInstallerSupport.class.getName()); |
| |
| @Messages({ |
| "searching_handle_single=Searching for \"{0}\" module on NetBeans plugin portal...", |
| "resolve_title_single=Resolve \"{0}\" Reference Problem", |
| "nodownload_header_single=\"{0}\" module has not been downloaded", |
| "nodownload_message_single=You can try to download \"{0}\" module again", |
| "active_handle_single=Activating {0}", |
| |
| "searching_handle=Searching for modules on NetBeans plugin portal...", |
| "resolve_title=Resolve Reference Problem", |
| "nodownload_header=Modules have not been downloaded", |
| "nodownload_message=You can try to download modules again", |
| "active_handle=Activating modules", |
| |
| "networkproblem_header=Unable to connect to the NetBeans plugin portal", |
| "networkproblem_message=Check your proxy settings or try again later. " |
| + "The server may be unavailable at the moment. " |
| + "You may also want to make sure that your firewall is not blocking network traffic.", |
| "proxy_button=&Proxy Settings...", |
| "tryagain_button=Try &Again" |
| }) |
| |
| private final Object[] closingOptions; |
| |
| private Object[] fullClosingOptions; |
| private JButton tryAgain; |
| private JButton proxySettings; |
| |
| public ModuleInstallerSupport(Object... alternativeOptions) { |
| this.closingOptions = alternativeOptions.clone(); |
| } |
| |
| public Object installPlugins(final String displayName, Set<String> cnbs) throws OperationException { |
| Collection<UpdateUnit> units = findModules(cnbs); |
| if (units == null) { |
| final String searchMessage = displayName != null |
| ? searching_handle_single(displayName) : searching_handle(); |
| final String resolveTitle = displayName != null |
| ? resolve_title_single(displayName) : resolve_title(); |
| |
| final ProgressHandle handle = ProgressHandleFactory.createHandle(searchMessage); |
| initButtons(); |
| final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searchMessage), |
| ProgressHandleFactory.createProgressComponent(handle)), resolveTitle, true, null); |
| handle.setInitialDelay(0); |
| handle.start(); |
| searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION}); |
| searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE); |
| final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching); |
| RP.post(new Runnable() { |
| |
| @Override |
| public void run() { |
| // May be first start, when no update lists have yet been downloaded. |
| try { |
| for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) { |
| p.refresh(handle, true); |
| } |
| // close searching |
| dlg.dispose(); |
| } catch (IOException ex) { |
| LOG.log(Level.FINE, ex.getMessage(), ex); |
| if (!dlg.isVisible()) { |
| LOG.fine("dialog not visible => do nothing"); |
| return; |
| } |
| DialogDescriptor networkProblem = new DialogDescriptor( |
| problemPanel(resolveTitle, networkproblem_message()), // message |
| networkproblem_header(), // title |
| true, // modal |
| null); |
| networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setAdditionalOptions(closingOptions); |
| networkProblem.setClosingOptions(fullClosingOptions); |
| networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
| Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
| networkProblemDialog.setVisible(true); |
| Object answer = networkProblem.getValue(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(answer) |
| || Arrays.asList(closingOptions).contains(answer) |
| || answer.equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */ ) { |
| LOG.fine("cancel network problem dialog"); |
| searching.setValue(answer); |
| dlg.dispose(); |
| } else if (tryAgain.equals(answer)) { |
| LOG.fine("try again searching"); |
| RP.post(this); |
| } else { |
| assert false : "Unknown " + answer; |
| } |
| } |
| } |
| }); |
| dlg.setVisible(true); |
| handle.finish(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) |
| || searching.getValue().equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */) { |
| LOG.log(Level.FINE, "user canceled searching for {0}", cnbs); |
| return showNoDownloadDialog(displayName, cnbs); |
| } else if (Arrays.asList(closingOptions).contains(searching.getValue())){ |
| return searching.getValue(); |
| } |
| units = findModules(cnbs); |
| if (units == null) { |
| LOG.log(Level.FINE, "could not find {0} on any update site", cnbs); |
| return showNoDownloadDialog(displayName, cnbs); |
| } |
| } |
| |
| List<UpdateUnit> toHandle = new ArrayList<UpdateUnit>(units); |
| OperationContainer<OperationSupport> oc = null; |
| |
| for (Iterator<UpdateUnit> it = toHandle.iterator(); it.hasNext(); ) { |
| UpdateUnit unit = it.next(); |
| |
| // check if module installed |
| if (unit.getInstalled() != null) { |
| if (LOG.isLoggable(Level.FINE)) { |
| LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled()); |
| } |
| if (unit.getInstalled().isEnabled()) { |
| it.remove(); |
| continue; |
| } else { |
| if (oc == null) { |
| oc = OperationContainer.createForEnable(); |
| } |
| if (!oc.canBeAdded(unit, unit.getInstalled())) { |
| throw new OperationException(OperationException.ERROR_TYPE.ENABLE, |
| "could not add " + unit.getInstalled() + " for activation"); |
| } |
| for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) { |
| oc.add(req); |
| } |
| it.remove(); |
| continue; |
| } |
| } |
| } |
| |
| if (oc != null) { |
| ProgressHandle activeHandle = ProgressHandleFactory.createHandle( |
| displayName != null ? active_handle_single(displayName) : active_handle()); |
| Restarter restarter = oc.getSupport().doOperation(activeHandle); |
| assert restarter == null : "No Restater need to make units active"; |
| } |
| |
| if (toHandle.isEmpty()) { |
| return null; |
| } |
| |
| OperationContainer<InstallSupport> ocInstall = OperationContainer.createForInstall(); |
| for (Iterator<UpdateUnit> it = toHandle.iterator(); it.hasNext(); ) { |
| UpdateUnit unit = it.next(); |
| |
| List<UpdateElement> updates = unit.getAvailableUpdates(); |
| if (updates.isEmpty()) { |
| throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "no updates for " + unit); |
| } |
| |
| UpdateElement element = updates.get(0); |
| if (!ocInstall.canBeAdded(unit, element)) { |
| throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "could not add " + element + " to updates"); |
| } |
| for (UpdateElement req : ocInstall.add(element).getRequiredElements()) { |
| ocInstall.add(req); |
| } |
| it.remove(); |
| } |
| assert toHandle.isEmpty() : "These unit were not handled " + toHandle; |
| |
| if (!PluginManager.openInstallWizard(ocInstall)) { |
| LOG.fine("user canceled PM"); |
| return showNoDownloadDialog(displayName, cnbs); |
| } |
| return null; |
| } |
| |
| private Collection<UpdateUnit> findModules(Set<String> cnbs) { |
| List<UpdateUnit> ret = new ArrayList<UpdateUnit>(cnbs.size()); |
| for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) { |
| if (cnbs.contains(unit.getCodeName())) { |
| ret.add(unit); |
| if (ret.size() == cnbs.size()) { |
| break; |
| } |
| } |
| } |
| if (ret.size() == cnbs.size()) { |
| return ret; |
| } |
| return null; |
| } |
| |
| private void initButtons() { |
| if (tryAgain != null) { |
| return ; |
| } |
| tryAgain = new JButton(); |
| proxySettings = new JButton(); |
| Mnemonics.setLocalizedText(tryAgain, tryagain_button()); |
| Mnemonics.setLocalizedText(proxySettings, proxy_button()); |
| proxySettings.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| LOG.fine("show proxy options"); |
| OptionsDisplayer.getDefault().open("General"); // NOI18N |
| } |
| }); |
| fullClosingOptions = new Object[closingOptions.length + 2]; |
| System.arraycopy(closingOptions, 0, fullClosingOptions, 0, closingOptions.length); |
| fullClosingOptions[fullClosingOptions.length - 2] = tryAgain; |
| fullClosingOptions[fullClosingOptions.length - 1] = NotifyDescriptor.CANCEL_OPTION; |
| } |
| |
| private Object showNoDownloadDialog(String displayName, Set<String> cnbs) throws OperationException { |
| DialogDescriptor networkProblem; |
| if (displayName != null) { |
| networkProblem = new DialogDescriptor( |
| problemPanel(nodownload_header_single(displayName), nodownload_message_single(displayName)), // message |
| resolve_title_single(displayName), // title |
| true, // modal |
| null); |
| } else { |
| networkProblem = new DialogDescriptor( |
| problemPanel(nodownload_header(), nodownload_message()), // message |
| resolve_title(), // title |
| true, // modal |
| null); |
| } |
| initButtons(); |
| networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setAdditionalOptions(closingOptions); |
| networkProblem.setClosingOptions(fullClosingOptions); |
| networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
| Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
| networkProblemDialog.setVisible(true); |
| Object answer = networkProblem.getValue(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(answer) |
| || Arrays.asList(closingOptions).contains(answer) |
| || answer.equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */ ) { |
| LOG.fine("cancel no download dialog"); |
| //throw new InterruptedException("user canceled download & install JUnit"); |
| return answer; |
| } else if (tryAgain.equals(answer)) { |
| LOG.fine("try again download()"); |
| return installPlugins(displayName, cnbs); |
| } else { |
| assert false : "Unknown " + answer; |
| } |
| assert false : "Unknown " + answer; |
| return NotifyDescriptor.DEFAULT_OPTION; |
| } |
| |
| private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) { |
| JPanel panel = new JPanel(); |
| progressLabel.setLabelFor(progressComponent); |
| javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel); |
| panel.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) |
| .addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) |
| .addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)) |
| .addContainerGap()) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addGap(96, 96, 96) |
| .addComponent(progressLabel) |
| .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) |
| .addContainerGap(109, Short.MAX_VALUE)) |
| ); |
| return panel; |
| } |
| |
| private static JPanel problemPanel(String header, String message) { |
| JPanel panel = new JPanel(); |
| JLabel jLabel1 = new javax.swing.JLabel(); |
| JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); |
| JTextArea jTextArea1 = new javax.swing.JTextArea(); |
| |
| jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD)); |
| jLabel1.setText(header); |
| |
| jTextArea1.setColumns(20); |
| jTextArea1.setEditable(false); |
| jTextArea1.setLineWrap(true); |
| jTextArea1.setWrapStyleWord(true); |
| jTextArea1.setRows(5); |
| jTextArea1.setText(message); |
| jTextArea1.setOpaque(false); |
| jScrollPane1.setViewportView(jTextArea1); |
| |
| javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel); |
| panel.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE) |
| .addGroup(layout.createSequentialGroup() |
| .addComponent(jLabel1) |
| .addGap(107, 107, 107))) |
| .addContainerGap()) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addComponent(jLabel1) |
| .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) |
| .addGap(82, 82, 82)) |
| ); |
| return panel; |
| } |
| |
| } |
| |