This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 196538
Collapse All | Expand All

(-)a/autoupdate.ui/apichanges.xml (+21 lines)
Lines 56-61 Link Here
56
    <!-- ACTUAL CHANGES BEGIN HERE: -->
56
    <!-- ACTUAL CHANGES BEGIN HERE: -->
57
57
58
    <changes>
58
    <changes>
59
        <change id="PluginManager.installPlugins">
60
            <api name="ui"/>
61
            <summary>PluginManager.install</summary>
62
            <version major="1" minor="35"/>
63
            <date day="13" month="2" year="2013"/>
64
            <author login="phejl"/>
65
            <compatibility addition="yes" binary="compatible" deletion="no"
66
                deprecation="no" semantic="compatible" source="compatible"
67
            />
68
            <description>
69
                <p>
70
                <code>PluginManager</code> ands its
71
                <a href="@TOP@/org/netbeans/modules/autoupdate/ui/api/PluginManager.html#installSingle(java.lang.String, java.lang.String, java.lang.Object[])">installSingle</a>
72
                and <a href="@TOP@/org/netbeans/modules/autoupdate/ui/api/PluginManager.html#install(java.util.Set, java.lang.Object[])">install</a>
73
                shows standard UI for easy installation of single plugin based
74
                on codenamebase.
75
                </p>
76
            </description>
77
            <class package="org.netbeans.modules.autoupdate.ui.api" name="PluginManager"/>
78
            <issue number="196538"/>
79
        </change>
59
        <change id="PluginManager.openInstallWizard">
80
        <change id="PluginManager.openInstallWizard">
60
            <api name="ui"/>
81
            <api name="ui"/>
61
            <summary>PluginManager.openInstallWizard</summary>
82
            <summary>PluginManager.openInstallWizard</summary>
(-)a/autoupdate.ui/manifest.mf (-1 / +1 lines)
Lines 2-7 Link Here
2
OpenIDE-Module: org.netbeans.modules.autoupdate.ui
2
OpenIDE-Module: org.netbeans.modules.autoupdate.ui
3
OpenIDE-Module-Install: org/netbeans/modules/autoupdate/ui/actions/Installer.class
3
OpenIDE-Module-Install: org/netbeans/modules/autoupdate/ui/actions/Installer.class
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/ui/resources/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/ui/resources/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.34
5
OpenIDE-Module-Specification-Version: 1.35
6
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Show-In-Client: false
7
AutoUpdate-Essential-Module: true
7
AutoUpdate-Essential-Module: true
(-)a/autoupdate.ui/nbproject/project.xml (+9 lines)
Lines 6-11 Link Here
6
            <code-name-base>org.netbeans.modules.autoupdate.ui</code-name-base>
6
            <code-name-base>org.netbeans.modules.autoupdate.ui</code-name-base>
7
            <module-dependencies>
7
            <module-dependencies>
8
                <dependency>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.19</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
9
                    <code-name-base>org.netbeans.api.progress</code-name-base>
18
                    <code-name-base>org.netbeans.api.progress</code-name-base>
10
                    <build-prerequisite/>
19
                    <build-prerequisite/>
11
                    <compile-dependency/>
20
                    <compile-dependency/>
(-)a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ModuleInstallerSupport.java (+417 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.autoupdate.ui;
43
44
import java.awt.Dialog;
45
import java.awt.event.ActionEvent;
46
import java.awt.event.ActionListener;
47
import java.io.IOException;
48
import java.util.ArrayList;
49
import java.util.Arrays;
50
import java.util.Collection;
51
import java.util.Iterator;
52
import java.util.List;
53
import java.util.Set;
54
import java.util.logging.Level;
55
import java.util.logging.Logger;
56
import javax.swing.JButton;
57
import javax.swing.JComponent;
58
import javax.swing.JLabel;
59
import javax.swing.JPanel;
60
import javax.swing.JScrollPane;
61
import javax.swing.JTextArea;
62
import org.netbeans.api.autoupdate.InstallSupport;
63
import org.netbeans.api.autoupdate.OperationContainer;
64
import org.netbeans.api.autoupdate.OperationException;
65
import org.netbeans.api.autoupdate.OperationSupport;
66
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
67
import org.netbeans.api.autoupdate.UpdateElement;
68
import org.netbeans.api.autoupdate.UpdateManager;
69
import org.netbeans.api.autoupdate.UpdateUnit;
70
import org.netbeans.api.autoupdate.UpdateUnitProvider;
71
import org.netbeans.api.autoupdate.UpdateUnitProviderFactory;
72
import org.netbeans.api.options.OptionsDisplayer;
73
import org.netbeans.api.progress.ProgressHandle;
74
import org.netbeans.api.progress.ProgressHandleFactory;
75
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
76
import org.openide.DialogDescriptor;
77
import org.openide.DialogDisplayer;
78
import org.openide.NotifyDescriptor;
79
import org.openide.awt.Mnemonics;
80
import org.openide.util.NbBundle.Messages;
81
import org.openide.util.RequestProcessor;
82
import static org.netbeans.modules.autoupdate.ui.Bundle.*;
83
84
/**
85
 *
86
 * @author Jesse Glick
87
 * @author Jan Lahoda
88
 * @author Petr Hejl
89
 */
90
public class ModuleInstallerSupport  {
91
    private static RequestProcessor RP = new RequestProcessor(ModuleInstallerSupport.class.getName(), 1);
92
    private static final Logger LOG = Logger.getLogger(ModuleInstallerSupport.class.getName());
93
94
    @Messages({
95
        "searching_handle_single=Searching for \"{0}\" module on NetBeans plugin portal...",
96
        "resolve_title_single=Resolve \"{0}\" Reference Problem",
97
        "nodownload_header_single=\"{0}\" module has not been downloaded",
98
        "nodownload_message_single=You can try to download \"{0}\" module again",
99
        "active_handle_single=Activating {0}",
100
101
        "searching_handle=Searching for modules on NetBeans plugin portal...",
102
        "resolve_title=Resolve Reference Problem",
103
        "nodownload_header=Modules have not been downloaded",
104
        "nodownload_message=You can try to download modules again",
105
        "active_handle=Activating modules",
106
107
        "networkproblem_header=Unable to connect  to the NetBeans plugin portal",
108
        "networkproblem_message=Check your proxy settings or try again later. "
109
            + "The server may be unavailable at the moment. "
110
            + "You may also want to make sure that your firewall is not blocking network traffic.",
111
        "proxy_button=&Proxy Settings...",
112
        "tryagain_button=Try &Again"
113
    })
114
115
    private final Object[] closingOptions;
116
117
    private Object[] fullClosingOptions;
118
    private JButton tryAgain;
119
    private JButton proxySettings;
120
121
    public ModuleInstallerSupport(Object... alternativeOptions) {
122
        this.closingOptions = alternativeOptions.clone();
123
    }
124
125
    public Object installPlugins(final String displayName, Set<String> cnbs) throws OperationException {
126
        Collection<UpdateUnit> units = findModules(cnbs);
127
        if (units == null) {
128
            final String searchMessage = displayName != null
129
                    ? searching_handle_single(displayName) : searching_handle();
130
            final String resolveTitle = displayName != null
131
                    ? resolve_title_single(displayName) : resolve_title();
132
133
            final ProgressHandle handle = ProgressHandleFactory.createHandle(searchMessage);
134
            initButtons();
135
            final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searchMessage),
136
                    ProgressHandleFactory.createProgressComponent(handle)), resolveTitle, true, null);
137
            handle.setInitialDelay(0);
138
            handle.start();
139
            searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION});
140
            searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
141
            final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching);
142
            RP.post(new Runnable() {
143
144
                @Override
145
                public void run() {
146
                    // May be first start, when no update lists have yet been downloaded.
147
                    try {
148
                        for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) {
149
                            p.refresh(handle, true);
150
                        }
151
                        // close searching
152
                        dlg.dispose();
153
                    } catch (IOException ex) {
154
                        LOG.log(Level.FINE, ex.getMessage(), ex);
155
                        if (!dlg.isVisible()) {
156
                            LOG.fine("dialog not visible => do nothing");
157
                            return;
158
                        }
159
                        DialogDescriptor networkProblem = new DialogDescriptor(
160
                                problemPanel(resolveTitle, networkproblem_message()), // message
161
                                networkproblem_header(), // title
162
                                true, // modal
163
                                null);
164
                        networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION});
165
                        networkProblem.setAdditionalOptions(closingOptions);
166
                        networkProblem.setClosingOptions(fullClosingOptions);
167
                        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
168
                        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
169
                        networkProblemDialog.setVisible(true);
170
                        Object answer = networkProblem.getValue();
171
                        if (NotifyDescriptor.CANCEL_OPTION.equals(answer)
172
                                || Arrays.asList(closingOptions).contains(answer)
173
                                || answer.equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */ ) {
174
                            LOG.fine("cancel network problem dialog");
175
                            searching.setValue(answer);
176
                            dlg.dispose();
177
                        } else if (tryAgain.equals(answer)) {
178
                            LOG.fine("try again searching");
179
                            RP.post(this);
180
                        } else {
181
                            assert false : "Unknown " + answer;
182
                        }
183
                    }
184
                }
185
            });
186
            dlg.setVisible(true);
187
            handle.finish();
188
            if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue())
189
                    || searching.getValue().equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */) {
190
                LOG.log(Level.FINE, "user canceled searching for {0}", cnbs);
191
                return showNoDownloadDialog(displayName, cnbs);
192
            } else if (Arrays.asList(closingOptions).contains(searching.getValue())){
193
                return searching.getValue();
194
            }
195
            units = findModules(cnbs);
196
            if (units == null) {
197
                LOG.log(Level.FINE, "could not find {0} on any update site", cnbs);
198
                return showNoDownloadDialog(displayName, cnbs);
199
            }
200
        }
201
202
        List<UpdateUnit> toHandle = new ArrayList<UpdateUnit>(units);
203
        OperationContainer<OperationSupport> oc = null;
204
205
        for (Iterator<UpdateUnit> it = toHandle.iterator(); it.hasNext(); ) {
206
            UpdateUnit unit = it.next();
207
208
            // check if module installed
209
            if (unit.getInstalled() != null) {
210
                if (LOG.isLoggable(Level.FINE)) {
211
                    LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled());
212
                }
213
                if (unit.getInstalled().isEnabled()) {
214
                    it.remove();
215
                    continue;
216
                } else {
217
                    if (oc == null) {
218
                        oc = OperationContainer.createForEnable();
219
                    }
220
                    if (!oc.canBeAdded(unit, unit.getInstalled())) {
221
                        throw new OperationException(OperationException.ERROR_TYPE.ENABLE,
222
                                "could not add " + unit.getInstalled() + " for activation");
223
                    }
224
                    for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) {
225
                        oc.add(req);
226
                    }
227
                    it.remove();
228
                    continue;
229
                }
230
            }
231
        }
232
233
        if (oc != null) {
234
            ProgressHandle activeHandle = ProgressHandleFactory.createHandle(
235
                    displayName != null ? active_handle_single(displayName) : active_handle());
236
            Restarter restarter = oc.getSupport().doOperation(activeHandle);
237
            assert restarter == null : "No Restater need to make units active";
238
        }
239
240
        if (toHandle.isEmpty()) {
241
            return null;
242
        }
243
244
        OperationContainer<InstallSupport> ocInstall = OperationContainer.createForInstall();
245
        for (Iterator<UpdateUnit> it = toHandle.iterator(); it.hasNext(); ) {
246
            UpdateUnit unit = it.next();
247
248
            List<UpdateElement> updates = unit.getAvailableUpdates();
249
            if (updates.isEmpty()) {
250
                throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "no updates for " + unit);
251
            }
252
253
            UpdateElement element = updates.get(0);
254
            if (!ocInstall.canBeAdded(unit, element)) {
255
                throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "could not add " + element + " to updates");
256
            }
257
            for (UpdateElement req : ocInstall.add(element).getRequiredElements()) {
258
                ocInstall.add(req);
259
            }
260
            it.remove();
261
        }
262
        assert toHandle.isEmpty() : "These unit were not handled " + toHandle;
263
264
        if (!PluginManager.openInstallWizard(ocInstall)) {
265
            LOG.fine("user canceled PM");
266
            return showNoDownloadDialog(displayName, cnbs);
267
        }
268
        return null;
269
    }
270
271
    private Collection<UpdateUnit> findModules(Set<String> cnbs) {
272
        List<UpdateUnit> ret = new ArrayList<UpdateUnit>(cnbs.size());
273
        for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) {
274
            if (cnbs.contains(unit.getCodeName())) {
275
                ret.add(unit);
276
                if (ret.size() == cnbs.size()) {
277
                    break;
278
                }
279
            }
280
        }
281
        if (ret.size() == cnbs.size()) {
282
            return ret;
283
        }
284
        return null;
285
    }
286
287
    private void initButtons() {
288
        if (tryAgain != null) {
289
            return ;
290
        }
291
        tryAgain = new JButton();
292
        proxySettings = new JButton();
293
        Mnemonics.setLocalizedText(tryAgain, tryagain_button());
294
        Mnemonics.setLocalizedText(proxySettings, proxy_button());
295
        proxySettings.addActionListener(new ActionListener() {
296
            @Override
297
            public void actionPerformed(ActionEvent e) {
298
                LOG.fine("show proxy options");
299
                OptionsDisplayer.getDefault().open("General"); // NOI18N
300
            }
301
        });
302
        fullClosingOptions = new Object[closingOptions.length + 2];
303
        System.arraycopy(closingOptions, 0, fullClosingOptions, 0, closingOptions.length);
304
        fullClosingOptions[fullClosingOptions.length - 2] = tryAgain;
305
        fullClosingOptions[fullClosingOptions.length - 1] = NotifyDescriptor.CANCEL_OPTION;
306
    }
307
308
    private Object showNoDownloadDialog(String displayName, Set<String> cnbs) throws OperationException {
309
        DialogDescriptor networkProblem;
310
        if (displayName != null) {
311
            networkProblem = new DialogDescriptor(
312
                    problemPanel(nodownload_header_single(displayName), nodownload_message_single(displayName)), // message
313
                    resolve_title_single(displayName), // title
314
                    true, // modal
315
                    null);
316
        } else {
317
            networkProblem = new DialogDescriptor(
318
                    problemPanel(nodownload_header(), nodownload_message()), // message
319
                    resolve_title(), // title
320
                    true, // modal
321
                    null);
322
        }
323
        initButtons();
324
        networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
325
        networkProblem.setAdditionalOptions(closingOptions);
326
        networkProblem.setClosingOptions(fullClosingOptions);
327
        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
328
        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
329
        networkProblemDialog.setVisible(true);
330
        Object answer = networkProblem.getValue();
331
        if (NotifyDescriptor.CANCEL_OPTION.equals(answer)
332
                || Arrays.asList(closingOptions).contains(answer)
333
                || answer.equals(NotifyDescriptor.DEFAULT_OPTION) /* escape */ ) {
334
            LOG.fine("cancel no download dialog");
335
            //throw new InterruptedException("user canceled download & install JUnit");
336
            return answer;
337
        } else if (tryAgain.equals(answer)) {
338
            LOG.fine("try again download()");
339
            return installPlugins(displayName, cnbs);
340
        } else {
341
            assert false : "Unknown " + answer;
342
        }
343
        assert false : "Unknown " + answer;
344
        return NotifyDescriptor.DEFAULT_OPTION;
345
    }
346
347
    private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) {
348
        JPanel panel = new JPanel();
349
        progressLabel.setLabelFor(progressComponent);
350
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
351
        panel.setLayout(layout);
352
        layout.setHorizontalGroup(
353
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
354
            .addGroup(layout.createSequentialGroup()
355
                .addContainerGap()
356
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
357
                    .addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
358
                    .addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
359
                .addContainerGap())
360
        );
361
        layout.setVerticalGroup(
362
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
363
            .addGroup(layout.createSequentialGroup()
364
                .addGap(96, 96, 96)
365
                .addComponent(progressLabel)
366
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
367
                .addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
368
                .addContainerGap(109, Short.MAX_VALUE))
369
        );
370
        return panel;
371
    }
372
373
    private static JPanel problemPanel(String header, String message) {
374
        JPanel panel = new JPanel();
375
        JLabel jLabel1 = new javax.swing.JLabel();
376
        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
377
        JTextArea jTextArea1 = new javax.swing.JTextArea();
378
379
        jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD));
380
        jLabel1.setText(header);
381
382
        jTextArea1.setColumns(20);
383
        jTextArea1.setEditable(false);
384
        jTextArea1.setLineWrap(true);
385
        jTextArea1.setWrapStyleWord(true);
386
        jTextArea1.setRows(5);
387
        jTextArea1.setText(message);
388
        jTextArea1.setOpaque(false);
389
        jScrollPane1.setViewportView(jTextArea1);
390
391
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
392
        panel.setLayout(layout);
393
        layout.setHorizontalGroup(
394
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
395
            .addGroup(layout.createSequentialGroup()
396
                .addContainerGap()
397
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
398
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
399
                    .addGroup(layout.createSequentialGroup()
400
                        .addComponent(jLabel1)
401
                        .addGap(107, 107, 107)))
402
                .addContainerGap())
403
        );
404
        layout.setVerticalGroup(
405
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
406
            .addGroup(layout.createSequentialGroup()
407
                .addContainerGap()
408
                .addComponent(jLabel1)
409
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
410
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
411
                .addGap(82, 82, 82))
412
        );
413
        return panel;
414
    }
415
416
}
417
(-)a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/api/PluginManager.java (-5 / +92 lines)
Lines 42-60 Link Here
42
42
43
package org.netbeans.modules.autoupdate.ui.api;
43
package org.netbeans.modules.autoupdate.ui.api;
44
44
45
import java.util.Collections;
45
import java.util.List;
46
import java.util.List;
47
import java.util.Set;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import org.netbeans.api.annotations.common.CheckForNull;
51
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.autoupdate.InstallSupport;
52
import org.netbeans.api.autoupdate.InstallSupport;
47
import org.netbeans.api.autoupdate.OperationContainer;
53
import org.netbeans.api.autoupdate.OperationContainer;
48
import org.netbeans.api.autoupdate.OperationContainer.OperationInfo;
54
import org.netbeans.api.autoupdate.OperationContainer.OperationInfo;
55
import org.netbeans.api.autoupdate.OperationException;
49
import org.netbeans.api.autoupdate.UpdateManager;
56
import org.netbeans.api.autoupdate.UpdateManager;
57
import org.netbeans.api.autoupdate.UpdateUnit;
58
import org.netbeans.modules.autoupdate.ui.ModuleInstallerSupport;
50
import org.netbeans.modules.autoupdate.ui.wizards.InstallUnitWizard;
59
import org.netbeans.modules.autoupdate.ui.wizards.InstallUnitWizard;
51
import org.netbeans.modules.autoupdate.ui.wizards.InstallUnitWizardModel;
60
import org.netbeans.modules.autoupdate.ui.wizards.InstallUnitWizardModel;
52
import org.netbeans.modules.autoupdate.ui.wizards.OperationWizardModel.OperationType;
61
import org.netbeans.modules.autoupdate.ui.wizards.OperationWizardModel.OperationType;
62
import org.openide.NotifyDescriptor;
63
import org.openide.util.Parameters;
53
64
54
/** Access to UI features of PluginManager that can be useful in other modules
65
/** Access to UI features of PluginManager that can be useful in other modules
55
 * as well. 
66
 * as well.
56
 * @since 1.21
67
 * @since 1.21
57
 * 
68
 *
58
 * @author Jirka Rechtacek
69
 * @author Jirka Rechtacek
59
 */
70
 */
60
public final class PluginManager {
71
public final class PluginManager {
Lines 63-72 Link Here
63
74
64
    /** Open standard dialog for installing set of modules. Shows it to the user,
75
    /** Open standard dialog for installing set of modules. Shows it to the user,
65
     * asks for confirmation, license acceptance, etc. The whole operation requires
76
     * asks for confirmation, license acceptance, etc. The whole operation requires
66
     * AWT dispatch thread access (to show the dialog) and blocks 
77
     * AWT dispatch thread access (to show the dialog) and blocks
67
     * (until the user clicks through), so either call from AWT dispatch thread
78
     * (until the user clicks through), so either call from AWT dispatch thread
68
     * directly, or be sure you hold no locks and block no progress of other
79
     * directly, or be sure you hold no locks and block no progress of other
69
     * threads to avoid deadlocks.
80
     * threads to avoid deadlocks.
81
     * <p>
82
     * Single module installation can be handled easily by
83
     * {@link #installSingle(java.lang.String, java.lang.String, java.lang.Object[])}.
70
<pre>
84
<pre>
71
{@link OperationContainer}<InstallSupport> container = OperationContainer.createForInstall();
85
{@link OperationContainer}<InstallSupport> container = OperationContainer.createForInstall();
72
for ({@link UpdateUnit} u : {@link UpdateManager#getUpdateUnits(org.netbeans.api.autoupdate.UpdateManager.TYPE[]) UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)}) {
86
for ({@link UpdateUnit} u : {@link UpdateManager#getUpdateUnits(org.netbeans.api.autoupdate.UpdateManager.TYPE[]) UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)}) {
Lines 79-88 Link Here
79
}
93
}
80
PluginManager.openInstallWizard(container);
94
PluginManager.openInstallWizard(container);
81
</pre>
95
</pre>
82
     * 
96
     *
83
     * @param container the container with list of modules for install
97
     * @param container the container with list of modules for install
84
     * @return true if all the requested modules were successfullly installed, 
98
     * @return true if all the requested modules were successfullly installed,
85
     *    false otherwise.
99
     *    false otherwise.
100
     * @see #installSingle(java.lang.String, java.lang.String, java.lang.Object[])
101
     * @see #install(java.util.Set, java.lang.Object[]) 
86
     */
102
     */
87
    public static boolean openInstallWizard(OperationContainer<InstallSupport> container) {
103
    public static boolean openInstallWizard(OperationContainer<InstallSupport> container) {
88
        if (container == null) {
104
        if (container == null) {
Lines 100-103 Link Here
100
        OperationType doOperation = info.getUpdateUnit ().getInstalled () == null ? OperationType.INSTALL : OperationType.UPDATE;
116
        OperationType doOperation = info.getUpdateUnit ().getInstalled () == null ? OperationType.INSTALL : OperationType.UPDATE;
101
        return new InstallUnitWizard ().invokeWizard (new InstallUnitWizardModel (doOperation, container), false);
117
        return new InstallUnitWizard ().invokeWizard (new InstallUnitWizardModel (doOperation, container), false);
102
    }
118
    }
119
120
    /** Open standard dialog for installing a module including declared dependencies.
121
     * Shows it to the user, asks for confirmation, license acceptance, etc.
122
     * The whole operation requires AWT dispatch thread access (to show the dialog)
123
     * and blocks (until the user clicks through), so either call from AWT dispatch
124
     * thread directly, or be sure you hold no locks and block no progress of other
125
     * threads to avoid deadlocks.
126
     *
127
     * @param codenamebase the codenamebase of module to install
128
     * @param displayName the display name of the module
129
     * @param alternativeOptions alternative options possibly displayed in error
130
     *             dialog user may choose if it is not possible to install the plugin;
131
     *             if chosen the option is return value of this method
132
     * @return <code>null</code> if the module has been successfully installed
133
     *             and/or activated, otherwise it returns the options user has
134
     *             selected in problem dialog, typically {@link NotifyDescriptor#DEFAULT_OPTION}
135
     *             (on esc), {@link NotifyDescriptor#CANCEL_OPTION} or
136
     *             any of <code>alternativeOptions</code>.
137
     * @since 1.35
138
     * @see #install(java.util.Set, java.lang.Object[]) 
139
     */
140
    @CheckForNull
141
    public static Object installSingle(@NonNull String codenamebase, @NonNull String displayName,
142
            @NonNull Object... alternativeOptions) {
143
        Parameters.notNull("cnb", codenamebase);
144
        Parameters.notNull("displayName", displayName);
145
        Parameters.notNull("alternativeOptions", alternativeOptions);
146
147
        try {
148
            return new ModuleInstallerSupport(alternativeOptions).installPlugins(displayName, Collections.singleton(codenamebase));
149
        } catch (OperationException ex) {
150
            Logger.getLogger(PluginManager.class.getName()).log(Level.WARNING, null, ex);
151
        }
152
        return NotifyDescriptor.DEFAULT_OPTION;
153
    }
154
155
    /** Open standard dialog for installing modules including declared dependencies.
156
     * Shows it to the user, asks for confirmation, license acceptance, etc.
157
     * The whole operation requires AWT dispatch thread access (to show the dialog)
158
     * and blocks (until the user clicks through), so either call from AWT dispatch
159
     * thread directly, or be sure you hold no locks and block no progress of other
160
     * threads to avoid deadlocks.
161
     *
162
     * @param codenamebases the codenamebases of modules to install; must contain at least
163
     *             one codenamebase
164
     * @param alternativeOptions alternative options possibly displayed in error
165
     *             dialog user may choose if it is not possible to install the plugin;
166
     *             if chosen the option is return value of this method
167
     * @return <code>null</code> if all the requested modules have been successfully
168
     *             installed and/or activated, otherwise it returns the options user has
169
     *             selected in problem dialog, typically {@link NotifyDescriptor#DEFAULT_OPTION}
170
     *             (on esc), {@link NotifyDescriptor#CANCEL_OPTION} or
171
     *             any of <code>alternativeOptions</code>.
172
     * @throws IllegalArgumentException if the <code>codenamebases</code> is empty
173
     * @since 1.35
174
     */
175
    @CheckForNull
176
    public static Object install(@NonNull Set<String> codenamebases, @NonNull Object... alternativeOptions) {
177
        Parameters.notNull("cnb", codenamebases);
178
        Parameters.notNull("alternativeOptions", alternativeOptions);
179
        if (codenamebases.isEmpty()) {
180
            throw new IllegalArgumentException("No plugins to install");
181
        }
182
183
        try {
184
            return new ModuleInstallerSupport(alternativeOptions).installPlugins(null, codenamebases);
185
        } catch (OperationException ex) {
186
            Logger.getLogger(PluginManager.class.getName()).log(Level.WARNING, null, ex);
187
        }
188
        return NotifyDescriptor.DEFAULT_OPTION;
189
    }
103
}
190
}
(-)a/code.analysis/nbproject/project.xml (-9 / +1 lines)
Lines 33-51 Link Here
33
                    </run-dependency>
33
                    </run-dependency>
34
                </dependency>
34
                </dependency>
35
                <dependency>
35
                <dependency>
36
                    <code-name-base>org.netbeans.modules.autoupdate.services</code-name-base>
37
                    <build-prerequisite/>
38
                    <compile-dependency/>
39
                    <run-dependency>
40
                        <specification-version>1.29</specification-version>
41
                    </run-dependency>
42
                </dependency>
43
                <dependency>
44
                    <code-name-base>org.netbeans.modules.autoupdate.ui</code-name-base>
36
                    <code-name-base>org.netbeans.modules.autoupdate.ui</code-name-base>
45
                    <build-prerequisite/>
37
                    <build-prerequisite/>
46
                    <compile-dependency/>
38
                    <compile-dependency/>
47
                    <run-dependency>
39
                    <run-dependency>
48
                        <specification-version>1.26</specification-version>
40
                        <specification-version>1.35</specification-version>
49
                    </run-dependency>
41
                    </run-dependency>
50
                </dependency>
42
                </dependency>
51
                <dependency>
43
                <dependency>
(-)a/code.analysis/src/org/netbeans/modules/analysis/ModuleInstallerSupport.java (-330 lines)
Lines 1-330 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.analysis;
44
45
import java.awt.event.ActionEvent;
46
import org.netbeans.api.autoupdate.OperationSupport;
47
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
48
import org.netbeans.api.options.OptionsDisplayer;
49
import javax.swing.JButton;
50
import javax.swing.JTextArea;
51
import javax.swing.JPanel;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
54
import java.awt.Dialog;
55
import java.awt.event.ActionListener;
56
import javax.swing.JComponent;
57
import javax.swing.JLabel;
58
import org.openide.DialogDisplayer;
59
import java.io.IOException;
60
import java.util.List;
61
import javax.swing.JScrollPane;
62
import org.netbeans.api.autoupdate.InstallSupport;
63
import org.netbeans.api.autoupdate.OperationContainer;
64
import org.netbeans.api.autoupdate.UpdateElement;
65
import org.netbeans.api.autoupdate.UpdateManager;
66
import org.netbeans.api.autoupdate.UpdateUnit;
67
import org.netbeans.api.autoupdate.UpdateUnitProvider;
68
import org.netbeans.api.autoupdate.UpdateUnitProviderFactory;
69
import org.netbeans.api.progress.ProgressHandle;
70
import org.netbeans.api.progress.ProgressHandleFactory;
71
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
72
import org.openide.DialogDescriptor;
73
import org.openide.NotifyDescriptor;
74
import org.openide.awt.Mnemonics;
75
import org.openide.util.NbBundle.Messages;
76
import org.openide.util.RequestProcessor;
77
import static org.netbeans.modules.analysis.Bundle.*;
78
79
/**
80
 * Copied and adjusted from the JUnitLibraryDownloader
81
 */
82
public class ModuleInstallerSupport  {
83
    private static RequestProcessor RP = new RequestProcessor(ModuleInstallerSupport.class.getName(), 1);
84
    private static final Logger LOG = Logger.getLogger(ModuleInstallerSupport.class.getName());
85
86
    @Messages({
87
        "searching_handle=Searching for \"{0}\" library on NetBeans plugin portal...",
88
        "resolve_title=Resolve \"{0}\" Reference Problem",
89
        "networkproblem_header=Unable to connect  to the NetBeans plugin portal",
90
        "networkproblem_message=Check your proxy settings or try again later. "
91
            + "The server may be unavailable at the moment. "
92
            + "You may also want to make sure that your firewall is not blocking network traffic.",
93
        "proxy_button=&Proxy Settings...",
94
        "tryagain_button=Try &Again",
95
        "nodownload_header=\"{0}\" module has not been downloaded",
96
        "nodownload_message=You can try to download \"{0}\" module again",
97
        "active_handle=Activating {0}"
98
    })
99
    
100
    private JButton tryAgain;
101
    private JButton proxySettings;
102
103
    @SuppressWarnings("SleepWhileInLoop")
104
    public boolean download(String cnb, final String displayName) throws Exception {
105
        UpdateUnit unit = findModule(cnb);
106
        if (unit == null) {
107
            final ProgressHandle handle = ProgressHandleFactory.createHandle(searching_handle(displayName));
108
            initButtons();
109
            final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searching_handle(displayName)),
110
                    ProgressHandleFactory.createProgressComponent(handle)), resolve_title(displayName), true, null);
111
            handle.setInitialDelay (0);
112
            handle.start ();
113
            searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION});
114
            searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
115
            final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching);
116
            RP.post(new Runnable() {
117
118
                @Override
119
                public void run() {
120
                    // May be first start, when no update lists have yet been downloaded.
121
                    try {
122
                        for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) {
123
                            p.refresh(handle, true);
124
                        }
125
                        // close searching
126
                        dlg.dispose();
127
                    } catch (IOException ex) {
128
                        LOG.log(Level.FINE, ex.getMessage(), ex);
129
                        if (! dlg.isVisible()) {
130
                            LOG.fine("dialog not visible => do nothing");
131
                            return ;
132
                        }
133
                        DialogDescriptor networkProblem = new DialogDescriptor(
134
                                problemPanel(resolve_title(displayName), networkproblem_message()), // message
135
                                networkproblem_header(), // title
136
                                true, // modal
137
                                null);
138
                        networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION});
139
                        networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
140
                        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
141
                        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
142
                        networkProblemDialog.setVisible(true);
143
                        Object answer = networkProblem.getValue();
144
                        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
145
                            LOG.fine("cancel network problem dialog");
146
                            searching.setValue(answer);
147
                            dlg.dispose();
148
                        } else if (tryAgain.equals(answer)) {
149
                            LOG.fine("try again searching");
150
                            RP.post(this);
151
                            assert false : "Unknown " + answer;
152
                        }
153
                    }
154
                }
155
            });
156
            dlg.setVisible(true);
157
            handle.finish();
158
            if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) || searching.getValue().equals(-1) /* escape */) {
159
                LOG.log(Level.FINE, "user canceled searching for {0}", cnb);
160
                return showNoDownloadDialog(cnb, displayName);
161
            }
162
            unit = findModule(cnb);
163
            if (unit == null) {
164
                LOG.log(Level.FINE, "could not find {0} on any update site", cnb);
165
                return showNoDownloadDialog(cnb, displayName);
166
            }
167
        }
168
        // check if module installed
169
        if (unit.getInstalled() != null) {
170
            LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled());
171
            if (unit.getInstalled().isEnabled()) {
172
                throw new Exception(unit.getInstalled() + " already installed and active");
173
            } else {
174
                // activate it
175
                OperationContainer<OperationSupport> oc = OperationContainer.createForEnable();
176
                if (!oc.canBeAdded(unit, unit.getInstalled())) {
177
                    throw new Exception("could not add " + unit.getInstalled() + " for activation");
178
                }
179
                for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) {
180
                    oc.add(req);
181
                }
182
                ProgressHandle activeHandle = ProgressHandleFactory.createHandle (active_handle(displayName));
183
                Restarter restarter = oc.getSupport().doOperation(activeHandle);
184
                assert restarter == null : "No Restater need to make " + unit.getInstalled() + " active";
185
                // XXX new library & build.properties apparently do not show up immediately... how to listen properly?
186
                return true;
187
            }
188
        }
189
        List<UpdateElement> updates = unit.getAvailableUpdates();
190
        if (updates.isEmpty()) {
191
            throw new Exception("no updates for " + unit);
192
        }
193
        OperationContainer<InstallSupport> oc = OperationContainer.createForInstall();
194
        UpdateElement element = updates.get(0);
195
        if (!oc.canBeAdded(unit, element)) {
196
            throw new Exception("could not add " + element + " to updates");
197
        }
198
        for (UpdateElement req : oc.add(element).getRequiredElements()) {
199
            oc.add(req);
200
        }
201
        if (!PluginManager.openInstallWizard(oc)) {
202
            LOG.fine("user canceled PM");
203
            return showNoDownloadDialog(cnb, displayName);
204
        }
205
        return true;
206
    }
207
208
    private UpdateUnit findModule(String cnb) throws IOException {
209
        for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) {
210
            if (unit.getCodeName().equals(cnb)) {
211
                return unit;
212
            }
213
        }
214
        return null;
215
    }
216
    
217
    private void initButtons() {
218
        if (tryAgain != null) {
219
            return ;
220
        }
221
        tryAgain = new JButton();
222
        proxySettings = new JButton();
223
        Mnemonics.setLocalizedText(tryAgain, tryagain_button());
224
        Mnemonics.setLocalizedText(proxySettings, proxy_button());
225
        proxySettings.addActionListener(new ActionListener() {
226
            @Override
227
            public void actionPerformed(ActionEvent e) {
228
                LOG.fine("show proxy options");
229
                OptionsDisplayer.getDefault().open("General"); // NOI18N
230
            }
231
        });
232
    }
233
    
234
    private boolean showNoDownloadDialog(String cnb, String displayName) throws Exception {
235
        DialogDescriptor networkProblem = new DialogDescriptor(
236
                problemPanel(nodownload_header(displayName), nodownload_message(displayName)), // message
237
                resolve_title(displayName), // title
238
                true, // modal
239
                null);
240
        initButtons();
241
        networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
242
        networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
243
        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
244
        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
245
        networkProblemDialog.setVisible(true);
246
        Object answer = networkProblem.getValue();
247
        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
248
            LOG.fine("cancel no download dialog");
249
            //throw new InterruptedException("user canceled download & install JUnit");
250
            return false;
251
        } else if (tryAgain.equals(answer)) {
252
            LOG.fine("try again download()");
253
            return download(cnb, displayName);
254
        } else {
255
            assert false : "Unknown " + answer;
256
        }
257
        assert false : "Unknown " + answer;
258
        return false;
259
    }
260
    
261
    private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) {
262
        JPanel panel = new JPanel();
263
        progressLabel.setLabelFor(progressComponent);
264
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
265
        panel.setLayout(layout);
266
        layout.setHorizontalGroup(
267
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
268
            .addGroup(layout.createSequentialGroup()
269
                .addContainerGap()
270
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
271
                    .addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
272
                    .addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
273
                .addContainerGap())
274
        );
275
        layout.setVerticalGroup(
276
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
277
            .addGroup(layout.createSequentialGroup()
278
                .addGap(96, 96, 96)
279
                .addComponent(progressLabel)
280
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
281
                .addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
282
                .addContainerGap(109, Short.MAX_VALUE))
283
        );
284
        return panel;
285
    }
286
    
287
    private static JPanel problemPanel(String header, String message) {
288
        JPanel panel = new JPanel();
289
        JLabel jLabel1 = new javax.swing.JLabel();
290
        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
291
        JTextArea jTextArea1 = new javax.swing.JTextArea();
292
293
        jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD));
294
        jLabel1.setText(header);
295
296
        jTextArea1.setColumns(20);
297
        jTextArea1.setEditable(false);
298
        jTextArea1.setLineWrap(true);
299
        jTextArea1.setWrapStyleWord(true);
300
        jTextArea1.setRows(5);
301
        jTextArea1.setText(message);
302
        jTextArea1.setOpaque(false);
303
        jScrollPane1.setViewportView(jTextArea1);
304
305
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
306
        panel.setLayout(layout);
307
        layout.setHorizontalGroup(
308
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
309
            .addGroup(layout.createSequentialGroup()
310
                .addContainerGap()
311
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
312
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
313
                    .addGroup(layout.createSequentialGroup()
314
                        .addComponent(jLabel1)
315
                        .addGap(107, 107, 107)))
316
                .addContainerGap())
317
        );
318
        layout.setVerticalGroup(
319
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
320
            .addGroup(layout.createSequentialGroup()
321
                .addContainerGap()
322
                .addComponent(jLabel1)
323
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
324
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
325
                .addGap(82, 82, 82))
326
        );
327
        return panel;
328
    }
329
330
}
(-)a/code.analysis/src/org/netbeans/modules/analysis/Utils.java (-6 / +2 lines)
Lines 45-51 Link Here
45
import java.util.HashSet;
45
import java.util.HashSet;
46
import java.util.Set;
46
import java.util.Set;
47
import org.netbeans.modules.analysis.spi.Analyzer.MissingPlugin;
47
import org.netbeans.modules.analysis.spi.Analyzer.MissingPlugin;
48
import org.openide.util.Exceptions;
48
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
49
49
50
/**
50
/**
51
 *
51
 *
Lines 57-67 Link Here
57
        Set<MissingPlugin> plugins = new HashSet<MissingPlugin>(inPlugins);
57
        Set<MissingPlugin> plugins = new HashSet<MissingPlugin>(inPlugins);
58
58
59
        for (MissingPlugin missing : plugins) {
59
        for (MissingPlugin missing : plugins) {
60
            try {
60
            PluginManager.installSingle(SPIAccessor.ACCESSOR.getCNB(missing), SPIAccessor.ACCESSOR.getDisplayName(missing));
61
                new ModuleInstallerSupport().download(SPIAccessor.ACCESSOR.getCNB(missing), SPIAccessor.ACCESSOR.getDisplayName(missing));
62
            } catch (Exception ex) {
63
                Exceptions.printStackTrace(ex);
64
            }
65
        }
61
        }
66
    }
62
    }
67
}
63
}
(-)a/findbugs.installer/src/org/netbeans/modules/findbugs/installer/FindBugsPanel.java (-5 / +2 lines)
Lines 41-46 Link Here
41
 */
41
 */
42
package org.netbeans.modules.findbugs.installer;
42
package org.netbeans.modules.findbugs.installer;
43
43
44
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
44
import org.openide.util.Exceptions;
45
import org.openide.util.Exceptions;
45
import org.openide.util.NbBundle.Messages;
46
import org.openide.util.NbBundle.Messages;
46
47
Lines 95-105 Link Here
95
96
96
    @Messages("FindBugs_Library=FindBugs Library")
97
    @Messages("FindBugs_Library=FindBugs Library")
97
    private void installActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_installActionPerformed
98
    private void installActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_installActionPerformed
98
        try {
99
        PluginManager.installSingle("org.netbeans.modules.findbugs", Bundle.FindBugs_Library());
99
            new ModuleInstallerSupport().download("org.netbeans.modules.findbugs", Bundle.FindBugs_Library());
100
        } catch (Exception ex) {
101
            Exceptions.printStackTrace(ex);
102
        }
103
    }//GEN-LAST:event_installActionPerformed
100
    }//GEN-LAST:event_installActionPerformed
104
101
105
    void load() {
102
    void load() {
(-)a/findbugs.installer/src/org/netbeans/modules/findbugs/installer/ModuleInstallerSupport.java (-331 lines)
Lines 1-331 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.findbugs.installer;
44
45
import java.awt.event.ActionEvent;
46
import org.netbeans.api.autoupdate.OperationSupport;
47
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
48
import org.netbeans.api.options.OptionsDisplayer;
49
import javax.swing.JButton;
50
import javax.swing.JTextArea;
51
import javax.swing.JPanel;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
54
import java.awt.Dialog;
55
import java.awt.event.ActionListener;
56
import javax.swing.JComponent;
57
import javax.swing.JLabel;
58
import org.openide.DialogDisplayer;
59
import java.io.IOException;
60
import java.util.List;
61
import javax.swing.JScrollPane;
62
import org.netbeans.api.autoupdate.InstallSupport;
63
import org.netbeans.api.autoupdate.OperationContainer;
64
import org.netbeans.api.autoupdate.UpdateElement;
65
import org.netbeans.api.autoupdate.UpdateManager;
66
import org.netbeans.api.autoupdate.UpdateUnit;
67
import org.netbeans.api.autoupdate.UpdateUnitProvider;
68
import org.netbeans.api.autoupdate.UpdateUnitProviderFactory;
69
import org.netbeans.api.progress.ProgressHandle;
70
import org.netbeans.api.progress.ProgressHandleFactory;
71
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
72
import org.openide.DialogDescriptor;
73
import org.openide.NotifyDescriptor;
74
import org.openide.awt.Mnemonics;
75
import org.openide.util.NbBundle.Messages;
76
import org.openide.util.RequestProcessor;
77
import static org.netbeans.modules.findbugs.installer.Bundle.*;
78
79
/**
80
 * Copied and adjusted from the JUnitLibraryDownloader
81
 */
82
public class ModuleInstallerSupport  {
83
    private static RequestProcessor RP = new RequestProcessor(ModuleInstallerSupport.class.getName(), 1);
84
    private static final Logger LOG = Logger.getLogger(ModuleInstallerSupport.class.getName());
85
86
    @Messages({
87
        "searching_handle=Searching for \"{0}\" library on NetBeans plugin portal...",
88
        "resolve_title=Resolve \"{0}\" Reference Problem",
89
        "networkproblem_header=Unable to connect  to the NetBeans plugin portal",
90
        "networkproblem_message=Check your proxy settings or try again later. "
91
            + "The server may be unavailable at the moment. "
92
            + "You may also want to make sure that your firewall is not blocking network traffic.",
93
        "proxy_button=&Proxy Settings...",
94
        "tryagain_button=Try &Again",
95
        "nodownload_header=\"{0}\" module has not been downloaded",
96
        "nodownload_message=You can try to download \"{0}\" module again",
97
        "active_handle=Activating {0}"
98
    })
99
    
100
    private JButton tryAgain;
101
    private JButton proxySettings;
102
103
    @SuppressWarnings("SleepWhileInLoop")
104
    public boolean download(String cnb, final String displayName) throws Exception {
105
        UpdateUnit unit = findModule(cnb);
106
        if (unit == null) {
107
            final ProgressHandle handle = ProgressHandleFactory.createHandle(searching_handle(displayName));
108
            initButtons();
109
            final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searching_handle(displayName)),
110
                    ProgressHandleFactory.createProgressComponent(handle)), resolve_title(displayName), true, null);
111
            handle.setInitialDelay (0);
112
            handle.start ();
113
            searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION});
114
            searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
115
            final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching);
116
            RP.post(new Runnable() {
117
118
                @Override
119
                public void run() {
120
                    // May be first start, when no update lists have yet been downloaded.
121
                    try {
122
                        for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) {
123
                            p.refresh(handle, true);
124
                        }
125
                        // close searching
126
                        dlg.dispose();
127
                    } catch (IOException ex) {
128
                        LOG.log(Level.FINE, ex.getMessage(), ex);
129
                        if (! dlg.isVisible()) {
130
                            LOG.fine("dialog not visible => do nothing");
131
                            return ;
132
                        }
133
                        DialogDescriptor networkProblem = new DialogDescriptor(
134
                                problemPanel(resolve_title(displayName), networkproblem_message()), // message
135
                                networkproblem_header(), // title
136
                                true, // modal
137
                                null);
138
                        networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION});
139
                        networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
140
                        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
141
                        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
142
                        networkProblemDialog.setVisible(true);
143
                        Object answer = networkProblem.getValue();
144
                        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
145
                            LOG.fine("cancel network problem dialog");
146
                            searching.setValue(answer);
147
                            dlg.dispose();
148
                        } else if (tryAgain.equals(answer)) {
149
                            LOG.fine("try again searching");
150
                            RP.post(this);
151
                        } else {
152
                            assert false : "Unknown " + answer;
153
                        }
154
                    }
155
                }
156
            });
157
            dlg.setVisible(true);
158
            handle.finish();
159
            if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) || searching.getValue().equals(-1) /* escape */) {
160
                LOG.log(Level.FINE, "user canceled searching for {0}", cnb);
161
                return showNoDownloadDialog(cnb, displayName);
162
            }
163
            unit = findModule(cnb);
164
            if (unit == null) {
165
                LOG.log(Level.FINE, "could not find {0} on any update site", cnb);
166
                return showNoDownloadDialog(cnb, displayName);
167
            }
168
        }
169
        // check if module installed
170
        if (unit.getInstalled() != null) {
171
            LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled());
172
            if (unit.getInstalled().isEnabled()) {
173
                throw new Exception(unit.getInstalled() + " already installed and active");
174
            } else {
175
                // activate it
176
                OperationContainer<OperationSupport> oc = OperationContainer.createForEnable();
177
                if (!oc.canBeAdded(unit, unit.getInstalled())) {
178
                    throw new Exception("could not add " + unit.getInstalled() + " for activation");
179
                }
180
                for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) {
181
                    oc.add(req);
182
                }
183
                ProgressHandle activeHandle = ProgressHandleFactory.createHandle (active_handle(displayName));
184
                Restarter restarter = oc.getSupport().doOperation(activeHandle);
185
                assert restarter == null : "No Restater need to make " + unit.getInstalled() + " active";
186
                // XXX new library & build.properties apparently do not show up immediately... how to listen properly?
187
                return true;
188
            }
189
        }
190
        List<UpdateElement> updates = unit.getAvailableUpdates();
191
        if (updates.isEmpty()) {
192
            throw new Exception("no updates for " + unit);
193
        }
194
        OperationContainer<InstallSupport> oc = OperationContainer.createForInstall();
195
        UpdateElement element = updates.get(0);
196
        if (!oc.canBeAdded(unit, element)) {
197
            throw new Exception("could not add " + element + " to updates");
198
        }
199
        for (UpdateElement req : oc.add(element).getRequiredElements()) {
200
            oc.add(req);
201
        }
202
        if (!PluginManager.openInstallWizard(oc)) {
203
            LOG.fine("user canceled PM");
204
            return showNoDownloadDialog(cnb, displayName);
205
        }
206
        return true;
207
    }
208
209
    private UpdateUnit findModule(String cnb) throws IOException {
210
        for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) {
211
            if (unit.getCodeName().equals(cnb)) {
212
                return unit;
213
            }
214
        }
215
        return null;
216
    }
217
    
218
    private void initButtons() {
219
        if (tryAgain != null) {
220
            return ;
221
        }
222
        tryAgain = new JButton();
223
        proxySettings = new JButton();
224
        Mnemonics.setLocalizedText(tryAgain, tryagain_button());
225
        Mnemonics.setLocalizedText(proxySettings, proxy_button());
226
        proxySettings.addActionListener(new ActionListener() {
227
            @Override
228
            public void actionPerformed(ActionEvent e) {
229
                LOG.fine("show proxy options");
230
                OptionsDisplayer.getDefault().open("General"); // NOI18N
231
            }
232
        });
233
    }
234
    
235
    private boolean showNoDownloadDialog(String cnb, String displayName) throws Exception {
236
        DialogDescriptor networkProblem = new DialogDescriptor(
237
                problemPanel(nodownload_header(displayName), nodownload_message(displayName)), // message
238
                resolve_title(displayName), // title
239
                true, // modal
240
                null);
241
        initButtons();
242
        networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
243
        networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
244
        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
245
        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
246
        networkProblemDialog.setVisible(true);
247
        Object answer = networkProblem.getValue();
248
        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
249
            LOG.fine("cancel no download dialog");
250
            //throw new InterruptedException("user canceled download & install JUnit");
251
            return false;
252
        } else if (tryAgain.equals(answer)) {
253
            LOG.fine("try again download()");
254
            return download(cnb, displayName);
255
        } else {
256
            assert false : "Unknown " + answer;
257
        }
258
        assert false : "Unknown " + answer;
259
        return false;
260
    }
261
    
262
    private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) {
263
        JPanel panel = new JPanel();
264
        progressLabel.setLabelFor(progressComponent);
265
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
266
        panel.setLayout(layout);
267
        layout.setHorizontalGroup(
268
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
269
            .addGroup(layout.createSequentialGroup()
270
                .addContainerGap()
271
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
272
                    .addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
273
                    .addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
274
                .addContainerGap())
275
        );
276
        layout.setVerticalGroup(
277
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
278
            .addGroup(layout.createSequentialGroup()
279
                .addGap(96, 96, 96)
280
                .addComponent(progressLabel)
281
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
282
                .addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
283
                .addContainerGap(109, Short.MAX_VALUE))
284
        );
285
        return panel;
286
    }
287
    
288
    private static JPanel problemPanel(String header, String message) {
289
        JPanel panel = new JPanel();
290
        JLabel jLabel1 = new javax.swing.JLabel();
291
        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
292
        JTextArea jTextArea1 = new javax.swing.JTextArea();
293
294
        jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD));
295
        jLabel1.setText(header);
296
297
        jTextArea1.setColumns(20);
298
        jTextArea1.setEditable(false);
299
        jTextArea1.setLineWrap(true);
300
        jTextArea1.setWrapStyleWord(true);
301
        jTextArea1.setRows(5);
302
        jTextArea1.setText(message);
303
        jTextArea1.setOpaque(false);
304
        jScrollPane1.setViewportView(jTextArea1);
305
306
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
307
        panel.setLayout(layout);
308
        layout.setHorizontalGroup(
309
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
310
            .addGroup(layout.createSequentialGroup()
311
                .addContainerGap()
312
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
313
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
314
                    .addGroup(layout.createSequentialGroup()
315
                        .addComponent(jLabel1)
316
                        .addGap(107, 107, 107)))
317
                .addContainerGap())
318
        );
319
        layout.setVerticalGroup(
320
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
321
            .addGroup(layout.createSequentialGroup()
322
                .addContainerGap()
323
                .addComponent(jLabel1)
324
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
325
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
326
                .addGap(82, 82, 82))
327
        );
328
        return panel;
329
    }
330
331
}
(-)a/junit/src/org/netbeans/modules/junit/JUnitLibraryDownloader.java (-301 / +12 lines)
Lines 42-83 Link Here
42
42
43
package org.netbeans.modules.junit;
43
package org.netbeans.modules.junit;
44
44
45
import java.awt.event.ActionEvent;
46
import org.netbeans.api.autoupdate.OperationSupport;
47
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
48
import org.netbeans.api.options.OptionsDisplayer;
49
import javax.swing.JButton;
45
import javax.swing.JButton;
50
import javax.swing.JTextArea;
51
import javax.swing.JPanel;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
46
import java.util.logging.Logger;
54
import java.awt.Dialog;
55
import java.awt.event.ActionListener;
56
import javax.swing.JComponent;
57
import javax.swing.JLabel;
58
import org.openide.DialogDisplayer;
59
import java.io.IOException;
60
import java.util.List;
61
import java.util.concurrent.Callable;
47
import java.util.concurrent.Callable;
62
import javax.swing.JScrollPane;
63
import org.netbeans.api.autoupdate.InstallSupport;
64
import org.netbeans.api.autoupdate.OperationContainer;
65
import org.netbeans.api.autoupdate.UpdateElement;
66
import org.netbeans.api.autoupdate.UpdateManager;
67
import org.netbeans.api.autoupdate.UpdateUnit;
68
import org.netbeans.api.autoupdate.UpdateUnitProvider;
69
import org.netbeans.api.autoupdate.UpdateUnitProviderFactory;
70
import org.netbeans.api.progress.ProgressHandle;
71
import org.netbeans.api.progress.ProgressHandleFactory;
72
import org.netbeans.api.project.libraries.Library;
48
import org.netbeans.api.project.libraries.Library;
73
import org.netbeans.api.project.libraries.LibraryManager;
49
import org.netbeans.api.project.libraries.LibraryManager;
74
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
50
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
75
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport.LibraryDefiner;
51
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport.LibraryDefiner;
76
import org.openide.DialogDescriptor;
77
import org.openide.NotifyDescriptor;
78
import org.openide.awt.Mnemonics;
52
import org.openide.awt.Mnemonics;
79
import org.openide.util.NbBundle.Messages;
53
import org.openide.util.NbBundle.Messages;
80
import org.openide.util.RequestProcessor;
81
import org.openide.util.lookup.ServiceProvider;
54
import org.openide.util.lookup.ServiceProvider;
82
import static org.netbeans.modules.junit.Bundle.*;
55
import static org.netbeans.modules.junit.Bundle.*;
83
56
Lines 85-111 Link Here
85
 * Defines JUnit 3.x/4.x libraries by downloading their defining modules.
58
 * Defines JUnit 3.x/4.x libraries by downloading their defining modules.
86
 */
59
 */
87
@ServiceProvider(service=LibraryDefiner.class)
60
@ServiceProvider(service=LibraryDefiner.class)
88
public class JUnitLibraryDownloader implements LibraryDefiner {
61
public class JUnitLibraryDefiner implements LibraryDefiner {
89
    private static RequestProcessor RP = new RequestProcessor(JUnitLibraryDownloader.class.getName(), 1);
90
    private static final Logger LOG = Logger.getLogger(JUnitLibraryDownloader.class.getName());
91
62
92
    @Messages({
63
    @Messages({
93
        "searching_handle=Searching for \"junit\" library on NetBeans plugin portal...",
94
        "resolve_title=Resolve \"junit\" Reference Problem",
95
        "networkproblem_header=Unable to connect  to the NetBeans plugin portal",
96
        "networkproblem_message=Check your proxy settings or try again later. "
97
            + "The server may be unavailable at the moment. "
98
            + "You may also want to make sure that your firewall is not blocking network traffic. \n\n"
99
            + "If you have the missing \"junit\" library, you can resolve the reference "
100
            + "problem manually using Library Manager.",
101
        "proxy_button=&Proxy Settings...",
102
        "library_button=&Library Manager...",
64
        "library_button=&Library Manager...",
103
        "tryagain_button=Try &Again",
65
        "library_name=junit"
104
        "nodownload_header=\"junit\" library has not been downloaded",
105
        "nodownload_message=You can try to download \"junit\" library again, or \n\n"
106
            + "if you have the missing \"junit\" library, you can resolve the reference "
107
            + "problem manually using Library Manager.",
108
        "active_handle=Activating JUnit"
109
    })
66
    })
110
    
67
    
111
    public @Override Callable<Library> missingLibrary(final String name) {
68
    public @Override Callable<Library> missingLibrary(final String name) {
Lines 113-384 Link Here
113
            return null;
70
            return null;
114
        }
71
        }
115
        return new Callable<Library>() {
72
        return new Callable<Library>() {
73
74
            @SuppressWarnings("SleepWhileInLoop")
116
            public @Override Library call() throws Exception {
75
            public @Override Library call() throws Exception {
117
                return download(name);
76
                JButton libraryManager = new JButton();
118
            }
77
                Mnemonics.setLocalizedText(libraryManager, library_button());
119
        };
78
                Object ret = PluginManager.installSingle("org.netbeans.modules.junitlib", library_name(), libraryManager);
120
    }
79
                if (libraryManager.equals(ret)) {
121
    
80
                    throw new Exception("junitlib failed/canceled to install properly, open library manager instaed");
122
    private JButton libraryManager;
123
    private JButton tryAgain;
124
    private JButton proxySettings;
125
126
    @SuppressWarnings("SleepWhileInLoop")
127
    private Library download(String name) throws Exception {
128
        UpdateUnit unit = findJUnitLib();
129
        if (unit == null) {
130
            final ProgressHandle handle = ProgressHandleFactory.createHandle(searching_handle());
131
            initButtons();
132
            final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searching_handle()),
133
                    ProgressHandleFactory.createProgressComponent(handle)), resolve_title(), true, null);
134
            handle.setInitialDelay (0);
135
            handle.start ();
136
            searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION});
137
            searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
138
            final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching);
139
            RP.post(new Runnable() {
140
141
                @Override
142
                public void run() {
143
                    // May be first start, when no update lists have yet been downloaded.
144
                    try {
145
                        for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) {
146
                            p.refresh(handle, true);
147
                        }
148
                        // close searching
149
                        dlg.dispose();
150
                    } catch (IOException ex) {
151
                        Logger.getLogger(JUnitLibraryDownloader.class.getName()).log(Level.FINE, ex.getMessage(), ex);
152
                        if (! dlg.isVisible()) {
153
                            LOG.fine("dialog not visible => do nothing");
154
                            return ;
155
                        }
156
                        DialogDescriptor networkProblem = new DialogDescriptor(
157
                                problemPanel(resolve_title(), networkproblem_message()), // message
158
                                networkproblem_header(), // title
159
                                true, // modal
160
                                null);
161
                        networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION});
162
                        networkProblem.setAdditionalOptions(new Object[] {libraryManager});
163
                        networkProblem.setClosingOptions(new Object[] {libraryManager, tryAgain, NotifyDescriptor.CANCEL_OPTION});
164
                        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
165
                        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
166
                        networkProblemDialog.setVisible(true);
167
                        Object answer = networkProblem.getValue();
168
                        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
169
                            LOG.fine("cancel network problem dialog");
170
                            searching.setValue(answer);
171
                            dlg.dispose();
172
                        } else if (tryAgain.equals(answer)) {
173
                            LOG.fine("try again searching");
174
                            RP.post(this);
175
                        } else if (libraryManager.equals(answer)) {
176
                            LOG.fine("open library manager");
177
                            searching.setValue(answer);
178
                            dlg.dispose();
179
                        } else {
180
                            assert false : "Unknown " + answer;
181
                        }
182
                    }
183
                }
81
                }
184
            });
185
            dlg.setVisible(true);
186
            handle.finish();
187
            if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) || searching.getValue().equals(-1) /* escape */) {
188
                LOG.fine("user canceled searching JUnit");
189
                return showNoDownloadDialog(name);
190
            } else if (libraryManager.equals(searching.getValue())) {
191
                throw new Exception("user canceled searching");
192
            }
193
            unit = findJUnitLib();
194
            if (unit == null) {
195
                LOG.fine("could not find junitlib on any update site");
196
                return showNoDownloadDialog(name);
197
            }
198
        }
199
        // check if JUnit installed
200
        if (unit.getInstalled() != null) {
201
            LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled());
202
            if (unit.getInstalled().isEnabled()) {
203
                throw new Exception(unit.getInstalled() + " already installed and active");
204
            } else {
205
                // activate it
206
                OperationContainer<OperationSupport> oc = OperationContainer.createForEnable();
207
                if (!oc.canBeAdded(unit, unit.getInstalled())) {
208
                    throw new Exception("could not add " + unit.getInstalled() + " for activation");
209
                }
210
                for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) {
211
                    oc.add(req);
212
                }
213
                ProgressHandle activeHandle = ProgressHandleFactory.createHandle (active_handle());
214
                Restarter restarter = oc.getSupport().doOperation(activeHandle);
215
                assert restarter == null : "No Restater need to make " + unit.getInstalled() + " active";
216
                // XXX new library & build.properties apparently do not show up immediately... how to listen properly?
82
                // XXX new library & build.properties apparently do not show up immediately... how to listen properly?
217
                for (int i = 0; i < 10; i++) {
83
                for (int i = 0; i < 20; i++) {
218
                    Library lib = LibraryManager.getDefault().getLibrary(name);
84
                    Library lib = LibraryManager.getDefault().getLibrary(name);
219
                    if (lib != null) {
85
                    if (lib != null) {
220
                        return lib;
86
                        return lib;
221
                    }
87
                    }
222
                    Thread.sleep(1000);
88
                    Thread.sleep(1000);
223
                }
89
                }
224
                LOG.info("junitlib failed to make active properly");
90
                return null;
225
                return showNoDownloadDialog(name);
226
            }
91
            }
227
        }
92
        };
228
        List<UpdateElement> updates = unit.getAvailableUpdates();
229
        if (updates.isEmpty()) {
230
            throw new Exception("no updates for " + unit);
231
        }
232
        OperationContainer<InstallSupport> oc = OperationContainer.createForInstall();
233
        UpdateElement element = updates.get(0);
234
        if (!oc.canBeAdded(unit, element)) {
235
            throw new Exception("could not add " + element + " to updates");
236
        }
237
        for (UpdateElement req : oc.add(element).getRequiredElements()) {
238
            oc.add(req);
239
        }
240
        if (!PluginManager.openInstallWizard(oc)) {
241
            LOG.fine("user canceled PM");
242
            return showNoDownloadDialog(name);
243
        }
244
        // XXX new library & build.properties apparently do not show up immediately... how to listen properly?
245
        for (int i = 0; i < 20; i++) {
246
            Library lib = LibraryManager.getDefault().getLibrary(name);
247
            if (lib != null) {
248
                return lib;
249
            }
250
            Thread.sleep(1000);
251
        }
252
        LOG.info("junitlib failed to install properly");
253
        return showNoDownloadDialog(name);
254
    }
255
256
    private UpdateUnit findJUnitLib() throws IOException {
257
        for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) {
258
            if (unit.getCodeName().equals("org.netbeans.modules.junitlib")) {
259
                return unit;
260
            }
261
        }
262
        return null;
263
    }
264
    
265
    private void initButtons() {
266
        if (libraryManager != null) {
267
            return ;
268
        }
269
        libraryManager = new JButton();
270
        tryAgain = new JButton();
271
        proxySettings = new JButton();
272
        Mnemonics.setLocalizedText(tryAgain, tryagain_button());
273
        Mnemonics.setLocalizedText(libraryManager, library_button());
274
        Mnemonics.setLocalizedText(proxySettings, proxy_button());
275
        proxySettings.addActionListener(new ActionListener() {
276
            @Override
277
            public void actionPerformed(ActionEvent e) {
278
                LOG.fine("show proxy options");
279
                OptionsDisplayer.getDefault().open("General"); // NOI18N
280
            }
281
        });
282
    }
283
    
284
    private Library showNoDownloadDialog(String name) throws Exception {
285
        DialogDescriptor networkProblem = new DialogDescriptor(
286
                problemPanel(nodownload_header(), nodownload_message()), // message
287
                resolve_title(), // title
288
                true, // modal
289
                null);
290
        initButtons();
291
        networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION});
292
        networkProblem.setAdditionalOptions(new Object[] {libraryManager});
293
        networkProblem.setClosingOptions(new Object[] {libraryManager, tryAgain, NotifyDescriptor.CANCEL_OPTION});
294
        networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE);
295
        Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem);
296
        networkProblemDialog.setVisible(true);
297
        Object answer = networkProblem.getValue();
298
        if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) {
299
            LOG.fine("cancel no download dialog");
300
            //throw new InterruptedException("user canceled download & install JUnit");
301
            return null;
302
        } else if (tryAgain.equals(answer)) {
303
            LOG.fine("try again download()");
304
            return download(name);
305
        } else if (libraryManager.equals(answer)) {
306
            LOG.fine("open library manager");
307
            throw new Exception("junitlib failed/canceled to install properly, open library manager instaed");            
308
        } else {
309
            assert false : "Unknown " + answer;
310
        }
311
        assert false : "Unknown " + answer;
312
        return null;
313
    }
314
    
315
    private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) {
316
        JPanel panel = new JPanel();
317
        progressLabel.setLabelFor(progressComponent);
318
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
319
        panel.setLayout(layout);
320
        layout.setHorizontalGroup(
321
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
322
            .addGroup(layout.createSequentialGroup()
323
                .addContainerGap()
324
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
325
                    .addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
326
                    .addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
327
                .addContainerGap())
328
        );
329
        layout.setVerticalGroup(
330
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
331
            .addGroup(layout.createSequentialGroup()
332
                .addGap(96, 96, 96)
333
                .addComponent(progressLabel)
334
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
335
                .addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
336
                .addContainerGap(109, Short.MAX_VALUE))
337
        );
338
        return panel;
339
    }
340
    
341
    private static JPanel problemPanel(String header, String message) {
342
        JPanel panel = new JPanel();
343
        JLabel jLabel1 = new javax.swing.JLabel();
344
        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
345
        JTextArea jTextArea1 = new javax.swing.JTextArea();
346
347
        jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD));
348
        jLabel1.setText(header);
349
350
        jTextArea1.setColumns(20);
351
        jTextArea1.setEditable(false);
352
        jTextArea1.setLineWrap(true);
353
        jTextArea1.setWrapStyleWord(true);
354
        jTextArea1.setRows(5);
355
        jTextArea1.setText(message);
356
        jTextArea1.setOpaque(false);
357
        jScrollPane1.setViewportView(jTextArea1);
358
359
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel);
360
        panel.setLayout(layout);
361
        layout.setHorizontalGroup(
362
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
363
            .addGroup(layout.createSequentialGroup()
364
                .addContainerGap()
365
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
366
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
367
                    .addGroup(layout.createSequentialGroup()
368
                        .addComponent(jLabel1)
369
                        .addGap(107, 107, 107)))
370
                .addContainerGap())
371
        );
372
        layout.setVerticalGroup(
373
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
374
            .addGroup(layout.createSequentialGroup()
375
                .addContainerGap()
376
                .addComponent(jLabel1)
377
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
378
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
379
                .addGap(82, 82, 82))
380
        );
381
        return panel;
382
    }
93
    }
383
94
384
}
95
}

Return to bug 196538