Added
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.List; |
49 |
import java.util.logging.Level; |
50 |
import java.util.logging.Logger; |
51 |
import javax.swing.JButton; |
52 |
import javax.swing.JComponent; |
53 |
import javax.swing.JLabel; |
54 |
import javax.swing.JPanel; |
55 |
import javax.swing.JScrollPane; |
56 |
import javax.swing.JTextArea; |
57 |
import org.netbeans.api.autoupdate.InstallSupport; |
58 |
import org.netbeans.api.autoupdate.OperationContainer; |
59 |
import org.netbeans.api.autoupdate.OperationException; |
60 |
import org.netbeans.api.autoupdate.OperationSupport; |
61 |
import org.netbeans.api.autoupdate.OperationSupport.Restarter; |
62 |
import org.netbeans.api.autoupdate.UpdateElement; |
63 |
import org.netbeans.api.autoupdate.UpdateManager; |
64 |
import org.netbeans.api.autoupdate.UpdateUnit; |
65 |
import org.netbeans.api.autoupdate.UpdateUnitProvider; |
66 |
import org.netbeans.api.autoupdate.UpdateUnitProviderFactory; |
67 |
import org.netbeans.api.options.OptionsDisplayer; |
68 |
import org.netbeans.api.progress.ProgressHandle; |
69 |
import org.netbeans.api.progress.ProgressHandleFactory; |
70 |
import org.netbeans.modules.autoupdate.ui.api.PluginManager; |
71 |
import org.openide.DialogDescriptor; |
72 |
import org.openide.DialogDisplayer; |
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.autoupdate.ui.Bundle.*; |
78 |
|
79 |
/** |
80 |
* |
81 |
* @author Jan Lahoda |
82 |
* @author Petr Hejl |
83 |
*/ |
84 |
public class ModuleInstallerSupport { |
85 |
private static RequestProcessor RP = new RequestProcessor(ModuleInstallerSupport.class.getName(), 1); |
86 |
private static final Logger LOG = Logger.getLogger(ModuleInstallerSupport.class.getName()); |
87 |
|
88 |
@Messages({ |
89 |
"searching_handle=Searching for \"{0}\" module on NetBeans plugin portal...", |
90 |
"resolve_title=Resolve \"{0}\" Reference Problem", |
91 |
"networkproblem_header=Unable to connect to the NetBeans plugin portal", |
92 |
"networkproblem_message=Check your proxy settings or try again later. " |
93 |
+ "The server may be unavailable at the moment. " |
94 |
+ "You may also want to make sure that your firewall is not blocking network traffic.", |
95 |
"proxy_button=&Proxy Settings...", |
96 |
"tryagain_button=Try &Again", |
97 |
"nodownload_header=\"{0}\" module has not been downloaded", |
98 |
"nodownload_message=You can try to download \"{0}\" module again", |
99 |
"active_handle=Activating {0}" |
100 |
}) |
101 |
|
102 |
private JButton tryAgain; |
103 |
private JButton proxySettings; |
104 |
|
105 |
@SuppressWarnings("SleepWhileInLoop") |
106 |
public boolean installPlugin(String cnb, final String displayName) throws OperationException { |
107 |
UpdateUnit unit = findModule(cnb); |
108 |
if (unit == null) { |
109 |
final ProgressHandle handle = ProgressHandleFactory.createHandle(searching_handle(displayName)); |
110 |
initButtons(); |
111 |
final DialogDescriptor searching = new DialogDescriptor(searchingPanel(new JLabel(searching_handle(displayName)), |
112 |
ProgressHandleFactory.createProgressComponent(handle)), resolve_title(displayName), true, null); |
113 |
handle.setInitialDelay (0); |
114 |
handle.start (); |
115 |
searching.setOptions(new Object[] {NotifyDescriptor.CANCEL_OPTION}); |
116 |
searching.setMessageType(NotifyDescriptor.PLAIN_MESSAGE); |
117 |
final Dialog dlg = DialogDisplayer.getDefault().createDialog(searching); |
118 |
RP.post(new Runnable() { |
119 |
|
120 |
@Override |
121 |
public void run() { |
122 |
// May be first start, when no update lists have yet been downloaded. |
123 |
try { |
124 |
for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) { |
125 |
p.refresh(handle, true); |
126 |
} |
127 |
// close searching |
128 |
dlg.dispose(); |
129 |
} catch (IOException ex) { |
130 |
LOG.log(Level.FINE, ex.getMessage(), ex); |
131 |
if (! dlg.isVisible()) { |
132 |
LOG.fine("dialog not visible => do nothing"); |
133 |
return ; |
134 |
} |
135 |
DialogDescriptor networkProblem = new DialogDescriptor( |
136 |
problemPanel(resolve_title(displayName), networkproblem_message()), // message |
137 |
networkproblem_header(), // title |
138 |
true, // modal |
139 |
null); |
140 |
networkProblem.setOptions(new Object[] {tryAgain, proxySettings, NotifyDescriptor.CANCEL_OPTION}); |
141 |
networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
142 |
networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
143 |
Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
144 |
networkProblemDialog.setVisible(true); |
145 |
Object answer = networkProblem.getValue(); |
146 |
if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) { |
147 |
LOG.fine("cancel network problem dialog"); |
148 |
searching.setValue(answer); |
149 |
dlg.dispose(); |
150 |
} else if (tryAgain.equals(answer)) { |
151 |
LOG.fine("try again searching"); |
152 |
RP.post(this); |
153 |
assert false : "Unknown " + answer; |
154 |
} |
155 |
} |
156 |
} |
157 |
}); |
158 |
dlg.setVisible(true); |
159 |
handle.finish(); |
160 |
if (NotifyDescriptor.CANCEL_OPTION.equals(searching.getValue()) || searching.getValue().equals(-1) /* escape */) { |
161 |
LOG.log(Level.FINE, "user canceled searching for {0}", cnb); |
162 |
return showNoDownloadDialog(cnb, displayName); |
163 |
} |
164 |
unit = findModule(cnb); |
165 |
if (unit == null) { |
166 |
LOG.log(Level.FINE, "could not find {0} on any update site", cnb); |
167 |
return showNoDownloadDialog(cnb, displayName); |
168 |
} |
169 |
} |
170 |
// check if module installed |
171 |
if (unit.getInstalled() != null) { |
172 |
if (LOG.isLoggable(Level.FINE)) { |
173 |
LOG.fine(unit.getInstalled() + " already installed. Is active? " + unit.getInstalled().isEnabled()); |
174 |
} |
175 |
if (unit.getInstalled().isEnabled()) { |
176 |
return true; |
177 |
//throw new Exception(unit.getInstalled() + " already installed and active"); |
178 |
} else { |
179 |
// activate it |
180 |
OperationContainer<OperationSupport> oc = OperationContainer.createForEnable(); |
181 |
if (!oc.canBeAdded(unit, unit.getInstalled())) { |
182 |
throw new OperationException(OperationException.ERROR_TYPE.ENABLE, |
183 |
"could not add " + unit.getInstalled() + " for activation"); |
184 |
} |
185 |
for (UpdateElement req : oc.add(unit.getInstalled()).getRequiredElements()) { |
186 |
oc.add(req); |
187 |
} |
188 |
ProgressHandle activeHandle = ProgressHandleFactory.createHandle (active_handle(displayName)); |
189 |
Restarter restarter = oc.getSupport().doOperation(activeHandle); |
190 |
assert restarter == null : "No Restater need to make " + unit.getInstalled() + " active"; |
191 |
// XXX new library & build.properties apparently do not show up immediately... how to listen properly? |
192 |
return true; |
193 |
} |
194 |
} |
195 |
List<UpdateElement> updates = unit.getAvailableUpdates(); |
196 |
if (updates.isEmpty()) { |
197 |
throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "no updates for " + unit); |
198 |
} |
199 |
OperationContainer<InstallSupport> oc = OperationContainer.createForInstall(); |
200 |
UpdateElement element = updates.get(0); |
201 |
if (!oc.canBeAdded(unit, element)) { |
202 |
throw new OperationException(OperationException.ERROR_TYPE.INSTALL, "could not add " + element + " to updates"); |
203 |
} |
204 |
for (UpdateElement req : oc.add(element).getRequiredElements()) { |
205 |
oc.add(req); |
206 |
} |
207 |
if (!PluginManager.openInstallWizard(oc)) { |
208 |
LOG.fine("user canceled PM"); |
209 |
return showNoDownloadDialog(cnb, displayName); |
210 |
} |
211 |
return true; |
212 |
} |
213 |
|
214 |
private UpdateUnit findModule(String cnb) { |
215 |
for (UpdateUnit unit : UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE)) { |
216 |
if (unit.getCodeName().equals(cnb)) { |
217 |
return unit; |
218 |
} |
219 |
} |
220 |
return null; |
221 |
} |
222 |
|
223 |
private void initButtons() { |
224 |
if (tryAgain != null) { |
225 |
return ; |
226 |
} |
227 |
tryAgain = new JButton(); |
228 |
proxySettings = new JButton(); |
229 |
Mnemonics.setLocalizedText(tryAgain, tryagain_button()); |
230 |
Mnemonics.setLocalizedText(proxySettings, proxy_button()); |
231 |
proxySettings.addActionListener(new ActionListener() { |
232 |
@Override |
233 |
public void actionPerformed(ActionEvent e) { |
234 |
LOG.fine("show proxy options"); |
235 |
OptionsDisplayer.getDefault().open("General"); // NOI18N |
236 |
} |
237 |
}); |
238 |
} |
239 |
|
240 |
private boolean showNoDownloadDialog(String cnb, String displayName) throws OperationException { |
241 |
DialogDescriptor networkProblem = new DialogDescriptor( |
242 |
problemPanel(nodownload_header(displayName), nodownload_message(displayName)), // message |
243 |
resolve_title(displayName), // title |
244 |
true, // modal |
245 |
null); |
246 |
initButtons(); |
247 |
networkProblem.setOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
248 |
networkProblem.setClosingOptions(new Object[] {tryAgain, NotifyDescriptor.CANCEL_OPTION}); |
249 |
networkProblem.setMessageType(NotifyDescriptor.WARNING_MESSAGE); |
250 |
Dialog networkProblemDialog = DialogDisplayer.getDefault().createDialog(networkProblem); |
251 |
networkProblemDialog.setVisible(true); |
252 |
Object answer = networkProblem.getValue(); |
253 |
if (NotifyDescriptor.CANCEL_OPTION.equals(answer) || answer.equals(-1) /* escape */ ) { |
254 |
LOG.fine("cancel no download dialog"); |
255 |
//throw new InterruptedException("user canceled download & install JUnit"); |
256 |
return false; |
257 |
} else if (tryAgain.equals(answer)) { |
258 |
LOG.fine("try again download()"); |
259 |
return installPlugin(cnb, displayName); |
260 |
} else { |
261 |
assert false : "Unknown " + answer; |
262 |
} |
263 |
assert false : "Unknown " + answer; |
264 |
return false; |
265 |
} |
266 |
|
267 |
private static JPanel searchingPanel(JLabel progressLabel, JComponent progressComponent) { |
268 |
JPanel panel = new JPanel(); |
269 |
progressLabel.setLabelFor(progressComponent); |
270 |
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel); |
271 |
panel.setLayout(layout); |
272 |
layout.setHorizontalGroup( |
273 |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
274 |
.addGroup(layout.createSequentialGroup() |
275 |
.addContainerGap() |
276 |
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) |
277 |
.addComponent(progressLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) |
278 |
.addComponent(progressComponent, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)) |
279 |
.addContainerGap()) |
280 |
); |
281 |
layout.setVerticalGroup( |
282 |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
283 |
.addGroup(layout.createSequentialGroup() |
284 |
.addGap(96, 96, 96) |
285 |
.addComponent(progressLabel) |
286 |
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
287 |
.addComponent(progressComponent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) |
288 |
.addContainerGap(109, Short.MAX_VALUE)) |
289 |
); |
290 |
return panel; |
291 |
} |
292 |
|
293 |
private static JPanel problemPanel(String header, String message) { |
294 |
JPanel panel = new JPanel(); |
295 |
JLabel jLabel1 = new javax.swing.JLabel(); |
296 |
JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); |
297 |
JTextArea jTextArea1 = new javax.swing.JTextArea(); |
298 |
|
299 |
jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD)); |
300 |
jLabel1.setText(header); |
301 |
|
302 |
jTextArea1.setColumns(20); |
303 |
jTextArea1.setEditable(false); |
304 |
jTextArea1.setLineWrap(true); |
305 |
jTextArea1.setWrapStyleWord(true); |
306 |
jTextArea1.setRows(5); |
307 |
jTextArea1.setText(message); |
308 |
jTextArea1.setOpaque(false); |
309 |
jScrollPane1.setViewportView(jTextArea1); |
310 |
|
311 |
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel); |
312 |
panel.setLayout(layout); |
313 |
layout.setHorizontalGroup( |
314 |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
315 |
.addGroup(layout.createSequentialGroup() |
316 |
.addContainerGap() |
317 |
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
318 |
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE) |
319 |
.addGroup(layout.createSequentialGroup() |
320 |
.addComponent(jLabel1) |
321 |
.addGap(107, 107, 107))) |
322 |
.addContainerGap()) |
323 |
); |
324 |
layout.setVerticalGroup( |
325 |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
326 |
.addGroup(layout.createSequentialGroup() |
327 |
.addContainerGap() |
328 |
.addComponent(jLabel1) |
329 |
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
330 |
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) |
331 |
.addGap(82, 82, 82)) |
332 |
); |
333 |
return panel; |
334 |
} |
335 |
|
336 |
} |
337 |
|