| /* |
| * 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.nbform; |
| |
| import java.awt.event.ActionEvent; |
| import org.netbeans.api.autoupdate.OperationSupport; |
| import org.netbeans.api.autoupdate.OperationSupport.Restarter; |
| import org.netbeans.api.options.OptionsDisplayer; |
| import javax.swing.JButton; |
| import javax.swing.JTextArea; |
| import javax.swing.JPanel; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import java.awt.Dialog; |
| import java.awt.event.ActionListener; |
| import javax.swing.JComponent; |
| import javax.swing.JLabel; |
| import org.openide.DialogDisplayer; |
| import java.io.IOException; |
| import java.util.List; |
| import java.util.concurrent.Callable; |
| import javax.swing.GroupLayout; |
| import javax.swing.JScrollPane; |
| import javax.swing.LayoutStyle; |
| import org.netbeans.api.autoupdate.InstallSupport; |
| import org.netbeans.api.autoupdate.OperationContainer; |
| 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.progress.ProgressHandle; |
| import org.netbeans.api.progress.ProgressHandleFactory; |
| import org.netbeans.api.project.libraries.Library; |
| import org.netbeans.api.project.libraries.LibraryManager; |
| import org.netbeans.modules.autoupdate.ui.api.PluginManager; |
| import org.netbeans.modules.form.FormUtils; |
| import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport.LibraryDefiner; |
| import org.openide.DialogDescriptor; |
| import org.openide.NotifyDescriptor; |
| import org.openide.awt.Mnemonics; |
| import org.openide.util.RequestProcessor; |
| import org.openide.util.lookup.ServiceProvider; |
| |
| /** |
| * Defines Swing Application Framework Library by downloading swingapplib module. |
| * The code is based on {@code JUnitLibraryDownloader} almost literally. |
| * |
| * @author Jan Stola |
| */ |
| @ServiceProvider(service=LibraryDefiner.class) |
| public class SwingAppLibDownloader implements LibraryDefiner { |
| private static RequestProcessor RP = new RequestProcessor(SwingAppLibDownloader.class.getName(), 1); |
| private static final Logger LOG = Logger.getLogger(SwingAppLibDownloader.class.getName()); |
| |
| @Override |
| public Callable<Library> missingLibrary(final String name) { |
| if (!name.matches("swing-app-framework")) { // NOI18N |
| return null; |
| } |
| return new Callable<Library>() { |
| @Override |
| public Library call() throws Exception { |
| return download(name); |
| } |
| }; |
| } |
| |
| private JButton libraryManager; |
| private JButton tryAgain; |
| private JButton proxySettings; |
| |
| @SuppressWarnings("SleepWhileInLoop") // NOI18N |
| private Library download(String name) throws Exception { |
| UpdateUnit unit = findSwingAppLibModule(); |
| if (unit == null) { |
| String searchingHandleTxt = FormUtils.getBundleString("swingapp.searching_handle"); // NOI18N |
| final ProgressHandle handle = ProgressHandleFactory.createHandle(searchingHandleTxt); |
| initButtons(); |
| final DialogDescriptor searching = new DialogDescriptor( |
| searchingPanel(new JLabel(searchingHandleTxt), ProgressHandleFactory.createProgressComponent(handle)), |
| FormUtils.getBundleString("swingapp.resolve_title"), true, null); // NOI18N |
| 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) { |
| Logger.getLogger(SwingAppLibDownloader.class.getName()).log(Level.FINE, ex.getMessage(), ex); |
| if (!dlg.isVisible()) { |
| LOG.fine("dialog not visible => do nothing"); // NOI18N |
| return ; |
| } |
| DialogDescriptor networkProblem = new DialogDescriptor( |
| problemPanel(FormUtils.getBundleString("swingapp.resolve_title"), FormUtils.getBundleString("swingapp.networkproblem_message")), // NOI18N |
| FormUtils.getBundleString("swingapp.networkproblem_header"), // NOI18N |
| true, // modal |
| null); |
| networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setAdditionalOptions(new Object[] {libraryManager}); |
| networkProblem.setClosingOptions(new Object[] {libraryManager, tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
| Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
| networkProblemDialog.setVisible(true); |
| Object answer = networkProblem.getValue(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) { |
| LOG.fine("cancel network problem dialog"); // NOI18N |
| searching.setValue(answer); |
| dlg.dispose(); |
| } else if (tryAgain.equals(answer)) { |
| LOG.fine("try again searching"); // NOI18N |
| RP.post(this); |
| } else if (libraryManager.equals(answer)) { |
| LOG.fine("open library manager"); // NOI18N |
| searching.setValue(answer); |
| dlg.dispose(); |
| } else { |
| assert false : "Unknown " + answer; // NOI18N |
| } |
| } |
| } |
| }); |
| dlg.setVisible(true); |
| handle.finish(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) || searching.getValue().equals(-1) /* escape */) { |
| LOG.fine("user canceled searching swingapplib"); // NOI18N |
| return showNoDownloadDialog(name); |
| } else if (libraryManager.equals(searching.getValue())) { |
| throw new Exception("user canceled searching"); // NOI18N |
| } |
| unit = findSwingAppLibModule(); |
| if (unit == null) { |
| LOG.fine("could not find swingapplib on any update site"); // NOI18N |
| return showNoDownloadDialog(name); |
| } |
| } |
| // check if swingapplib is installed |
| if (unit.getInstalled() != null) { |
| LOG.log(Level.FINE, "{0} already installed. Is active? {1}", new Object[]{unit.getInstalled(), unit.getInstalled().isEnabled()}); //NOI18N |
| if (unit.getInstalled().isEnabled()) { |
| throw new Exception(unit.getInstalled() + " already installed and active"); // NOI18N |
| } else { |
| // activate it |
| OperationContainer<OperationSupport> oc = OperationContainer.createForEnable(); |
| if (!oc.canBeAdded(unit, unit.getInstalled())) { |
| throw new Exception("could not add " + unit.getInstalled() + " for activation"); // NOI18N |
| } |
| for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) { |
| oc.add(req); |
| } |
| ProgressHandle activeHandle = ProgressHandleFactory.createHandle (FormUtils.getBundleString("swingapp.active_handle")); // NOI18N |
| Restarter restarter = oc.getSupport().doOperation(activeHandle); |
| assert restarter == null : "No Restater need to make " + unit.getInstalled() + " active"; // NOI18N |
| // XXX new library & build.properties apparently do not show up immediately... how to listen properly? |
| for (int i = 0; i < 10; i++) { |
| Library lib = LibraryManager.getDefault().getLibrary(name); |
| if (lib != null) { |
| return lib; |
| } |
| Thread.sleep(1000); |
| } |
| LOG.info("swingapplib failed to make active properly"); // NOI18N |
| return showNoDownloadDialog(name); |
| } |
| } |
| List<UpdateElement> updates = unit.getAvailableUpdates(); |
| if (updates.isEmpty()) { |
| throw new Exception("no updates for " + unit); // NOI18N |
| } |
| OperationContainer<InstallSupport> oc = OperationContainer.createForInstall(); |
| UpdateElement element = updates.get(0); |
| if (!oc.canBeAdded(unit, element)) { |
| throw new Exception("could not add " + element + " to updates"); // NOI18N |
| } |
| for (UpdateElement req : oc.add(element).getRequiredElements()) { |
| oc.add(req); |
| } |
| if (!PluginManager.openInstallWizard(oc)) { |
| LOG.fine("user canceled PM"); // NOI18N |
| return showNoDownloadDialog(name); |
| } |
| // XXX new library & build.properties apparently do not show up immediately... how to listen properly? |
| for (int i = 0; i < 10; i++) { |
| Library lib = LibraryManager.getDefault().getLibrary(name); |
| if (lib != null) { |
| return lib; |
| } |
| Thread.sleep(1000); |
| } |
| LOG.info("swingapplib failed to install properly"); // NOI18N |
| return showNoDownloadDialog(name); |
| } |
| |
| private UpdateUnit findSwingAppLibModule() throws IOException { |
| for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) { |
| if (unit.getCodeName().equals("org.netbeans.modules.swingapplib")) { // NOI18N |
| return unit; |
| } |
| } |
| return null; |
| } |
| |
| private void initButtons() { |
| if (libraryManager != null) { |
| return ; |
| } |
| libraryManager = new JButton(); |
| tryAgain = new JButton(); |
| proxySettings = new JButton(); |
| Mnemonics.setLocalizedText(tryAgain, FormUtils.getBundleString("swingapp.tryagain_button")); // NOI18N |
| Mnemonics.setLocalizedText(libraryManager, FormUtils.getBundleString("swingapp.library_button")); // NOI18N |
| Mnemonics.setLocalizedText(proxySettings, FormUtils.getBundleString("swingapp.proxy_button")); // NOI18N |
| proxySettings.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| LOG.fine("show proxy options"); // NOI18N |
| OptionsDisplayer.getDefault().open("General"); // NOI18N |
| } |
| }); |
| } |
| |
| private Library showNoDownloadDialog(String name) throws Exception { |
| DialogDescriptor networkProblem = new DialogDescriptor( |
| problemPanel(FormUtils.getBundleString("swingapp.nodownload_header"), FormUtils.getBundleString("swingapp.nodownload_message")), // NOI18N |
| FormUtils.getBundleString("swingapp.resolve_title"), // NOI18N |
| true, // modal |
| null); |
| initButtons(); |
| networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setAdditionalOptions(new Object[] {libraryManager}); |
| networkProblem.setClosingOptions(new Object[] {libraryManager, tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
| networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
| Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
| networkProblemDialog.setVisible(true); |
| Object answer = networkProblem.getValue(); |
| if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) { |
| LOG.fine("cancel no download dialog"); // NOI18N |
| return null; |
| } else if (tryAgain.equals(answer)) { |
| LOG.fine("try again download()"); // NOI18N |
| return download(name); |
| } else if (libraryManager.equals(answer)) { |
| LOG.fine("open library manager"); |
| throw new Exception("swingapplib failed/canceled to install properly, open library manager instaed"); |
| } else { |
| assert false : "Unknown " + answer; // NOI18N |
| } |
| return null; |
| } |
| |
| private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) { |
| JPanel panel = new JPanel(); |
| progressLabel.setLabelFor(progressComponent); |
| javax.swing.GroupLayout layout = new GroupLayout(panel); |
| panel.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) |
| .addComponent(progressLabel, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) |
| .addComponent(progressComponent, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)) |
| .addContainerGap()) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addGap(96, 96, 96) |
| .addComponent(progressLabel) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(progressComponent, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, 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 GroupLayout(panel); |
| panel.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE) |
| .addGroup(layout.createSequentialGroup() |
| .addComponent(jLabel1) |
| .addGap(107, 107, 107))) |
| .addContainerGap()) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addComponent(jLabel1) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) |
| .addGap(82, 82, 82)) |
| ); |
| return panel; |
| } |
| |
| } |