api/src/org/netbeans/modules/jackpot30/impl/indexing/options/CustomizeRemoteIndex.java
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2010-2011 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2010-2011 Sun Microsystems, Inc.
39 package org.netbeans.modules.jackpot30.impl.indexing.options;
41 import java.awt.Component;
43 import java.net.MalformedURLException;
44 import java.net.URISyntaxException;
46 import java.text.DateFormat;
47 import java.util.Collection;
48 import java.util.Date;
49 import java.util.HashMap;
51 import java.util.concurrent.atomic.AtomicBoolean;
52 import java.util.concurrent.atomic.AtomicReference;
53 import java.util.logging.Level;
54 import java.util.logging.Logger;
55 import javax.swing.DefaultComboBoxModel;
56 import javax.swing.DefaultListCellRenderer;
57 import javax.swing.JButton;
58 import javax.swing.JFileChooser;
59 import javax.swing.JList;
60 import javax.swing.JTextField;
61 import javax.swing.SwingUtilities;
62 import javax.swing.UIManager;
63 import javax.swing.event.DocumentEvent;
64 import javax.swing.event.DocumentListener;
65 import org.codeviation.pojson.Pojson;
66 import org.netbeans.modules.jackpot30.impl.WebUtilities;
67 import org.netbeans.modules.jackpot30.impl.indexing.IndexInfo;
68 import org.netbeans.modules.jackpot30.impl.indexing.RemoteIndex;
69 import org.openide.NotificationLineSupport;
70 import org.openide.util.RequestProcessor;
76 public class CustomizeRemoteIndex extends javax.swing.JPanel {
78 private final JButton okButton;
80 public CustomizeRemoteIndex(JButton okButton) {
81 this.okButton = okButton;
83 DocumentListener updateErrorsListener = new DocumentListener() {
84 public void insertUpdate(DocumentEvent e) {
87 public void removeUpdate(DocumentEvent e) {
90 public void changedUpdate(DocumentEvent e) {}
92 folder.getDocument().addDocumentListener(updateErrorsListener);
93 indexURL.getDocument().addDocumentListener(new DocumentListener() {
94 public void insertUpdate(DocumentEvent e) {
97 public void removeUpdate(DocumentEvent e) {
100 public void changedUpdate(DocumentEvent e) {
103 indexInfo.setFont(UIManager.getFont("Label.font"));
104 indexInfo.setBackground(UIManager.getColor("Label.background"));
105 indexInfo.setDisabledTextColor(UIManager.getColor("Label.foreground"));
108 /** This method is called from within the constructor to
109 * initialize the form.
110 * WARNING: Do NOT modify this code. The content of this method is
111 * always regenerated by the Form Editor.
113 @SuppressWarnings("unchecked")
114 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
115 private void initComponents() {
116 java.awt.GridBagConstraints gridBagConstraints;
118 buttonGroup1 = new javax.swing.ButtonGroup();
119 folderPanel = new javax.swing.JPanel();
120 folderLabel = new javax.swing.JLabel();
121 folderChooser = new javax.swing.JButton();
122 folder = new javax.swing.JTextField();
123 indexInfo = new javax.swing.JTextArea();
124 remoteIndexPanel = new javax.swing.JPanel();
125 indexURL = new javax.swing.JTextField();
126 indexURLLabel = new javax.swing.JLabel();
127 subIndex = new javax.swing.JComboBox();
128 jLabel1 = new javax.swing.JLabel();
130 setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 12));
131 setLayout(new java.awt.GridBagLayout());
133 folderPanel.setLayout(new java.awt.GridBagLayout());
135 org.openide.awt.Mnemonics.setLocalizedText(folderLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderLabel.text")); // NOI18N
136 gridBagConstraints = new java.awt.GridBagConstraints();
137 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
138 gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6);
139 folderPanel.add(folderLabel, gridBagConstraints);
141 org.openide.awt.Mnemonics.setLocalizedText(folderChooser, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderChooser.text")); // NOI18N
142 folderChooser.addActionListener(new java.awt.event.ActionListener() {
143 public void actionPerformed(java.awt.event.ActionEvent evt) {
144 folderChooserActionPerformed(evt);
147 gridBagConstraints = new java.awt.GridBagConstraints();
148 gridBagConstraints.gridx = 2;
149 gridBagConstraints.gridy = 0;
150 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
151 gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
152 folderPanel.add(folderChooser, gridBagConstraints);
154 folder.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folder.text")); // NOI18N
155 gridBagConstraints = new java.awt.GridBagConstraints();
156 gridBagConstraints.gridx = 1;
157 gridBagConstraints.gridy = 0;
158 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
159 gridBagConstraints.weightx = 1.0;
160 folderPanel.add(folder, gridBagConstraints);
162 gridBagConstraints = new java.awt.GridBagConstraints();
163 gridBagConstraints.gridx = 0;
164 gridBagConstraints.gridy = 0;
165 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
166 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
167 gridBagConstraints.weightx = 1.0;
168 add(folderPanel, gridBagConstraints);
170 indexInfo.setColumns(20);
171 indexInfo.setEditable(false);
172 indexInfo.setRows(5);
173 indexInfo.setBorder(null);
174 gridBagConstraints = new java.awt.GridBagConstraints();
175 gridBagConstraints.gridx = 0;
176 gridBagConstraints.gridy = 2;
177 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
178 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
179 gridBagConstraints.weightx = 1.0;
180 gridBagConstraints.weighty = 1.0;
181 gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
182 add(indexInfo, gridBagConstraints);
184 indexURL.setColumns(40);
185 indexURL.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURL.text")); // NOI18N
187 org.openide.awt.Mnemonics.setLocalizedText(indexURLLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURLLabel.text")); // NOI18N
189 subIndex.addActionListener(new java.awt.event.ActionListener() {
190 public void actionPerformed(java.awt.event.ActionEvent evt) {
191 subIndexActionPerformed(evt);
195 org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.jLabel1.text")); // NOI18N
197 javax.swing.GroupLayout remoteIndexPanelLayout = new javax.swing.GroupLayout(remoteIndexPanel);
198 remoteIndexPanel.setLayout(remoteIndexPanelLayout);
199 remoteIndexPanelLayout.setHorizontalGroup(
200 remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
201 .addGroup(remoteIndexPanelLayout.createSequentialGroup()
203 .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
204 .addGroup(remoteIndexPanelLayout.createSequentialGroup()
206 .addComponent(jLabel1)
207 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
208 .addComponent(subIndex, 0, 589, Short.MAX_VALUE))
209 .addGroup(remoteIndexPanelLayout.createSequentialGroup()
210 .addComponent(indexURLLabel)
211 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
212 .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
215 remoteIndexPanelLayout.setVerticalGroup(
216 remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
217 .addGroup(remoteIndexPanelLayout.createSequentialGroup()
219 .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
220 .addComponent(indexURLLabel)
221 .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
222 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
223 .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
224 .addComponent(jLabel1)
225 .addComponent(subIndex, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
226 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
229 gridBagConstraints = new java.awt.GridBagConstraints();
230 gridBagConstraints.gridx = 0;
231 gridBagConstraints.gridy = 1;
232 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
233 gridBagConstraints.weightx = 1.0;
234 add(remoteIndexPanel, gridBagConstraints);
235 }// </editor-fold>//GEN-END:initComponents
237 private void folderChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_folderChooserActionPerformed
238 showFileChooser(folder);
239 }//GEN-LAST:event_folderChooserActionPerformed
241 private void subIndexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_subIndexActionPerformed
242 subindexSelectionUpdated();
243 }//GEN-LAST:event_subIndexActionPerformed
245 // Variables declaration - do not modify//GEN-BEGIN:variables
246 private javax.swing.ButtonGroup buttonGroup1;
247 private javax.swing.JTextField folder;
248 private javax.swing.JButton folderChooser;
249 private javax.swing.JLabel folderLabel;
250 private javax.swing.JPanel folderPanel;
251 private javax.swing.JTextArea indexInfo;
252 private javax.swing.JTextField indexURL;
253 private javax.swing.JLabel indexURLLabel;
254 private javax.swing.JLabel jLabel1;
255 private javax.swing.JPanel remoteIndexPanel;
256 private javax.swing.JComboBox subIndex;
257 // End of variables declaration//GEN-END:variables
259 private void showFileChooser(JTextField folder) {
260 JFileChooser c = new JFileChooser();
262 c.setSelectedFile(new File(folder.getText()));
263 c.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
264 c.setMultiSelectionEnabled(false);
265 c.setApproveButtonText("Select");
267 if (c.showDialog(this, null) == JFileChooser.APPROVE_OPTION) {
268 folder.setText(c.getSelectedFile().getAbsolutePath());
272 public void setIndex(RemoteIndex index) {
273 folder.setText(index.folder);
274 indexURL.setText(index.remote.toExternalForm());
275 subIndex.setSelectedItem(index.remoteSegment);
278 public RemoteIndex getIndex() {
280 return RemoteIndex.create(folder.getText(), new URL(indexURL.getText()), (String) subIndex.getSelectedItem());
281 } catch (MalformedURLException ex) {
282 throw new IllegalStateException(ex);
286 private NotificationLineSupport notificationSupport;
288 public void setNotificationSupport(NotificationLineSupport notificationSupport) {
289 this.notificationSupport = notificationSupport;
292 private void updateErrors() {
293 notificationSupport.clearMessages();
295 File folderFile = new File(folder.getText());
297 if (!folderFile.exists()) {
298 notificationSupport.setErrorMessage("Specified directory does not exist.");
299 okButton.setEnabled(false);
303 if (!folderFile.isDirectory()) {
304 notificationSupport.setErrorMessage("Specified directory is not directory.");
305 okButton.setEnabled(false);
309 if (checkingIndexURL.get()) {
310 notificationSupport.setInformationMessage("Checking index URL");
311 okButton.setEnabled(false);
315 String urlError = checkingIndexURLError.get();
317 if (urlError != null) {
318 notificationSupport.setErrorMessage(urlError);
319 okButton.setEnabled(false);
323 okButton.setEnabled(true);
326 private final AtomicBoolean checkingIndexURL = new AtomicBoolean();
327 private final AtomicReference<String> checkingIndexURLContentCopy = new AtomicReference<String>();
328 private final AtomicReference<String> checkingIndexURLError = new AtomicReference<String>();
330 private void indexURLUpdated() {
331 checkingIndexURLContentCopy.set(indexURL.getText());
332 urlCheckerTask.cancel();
333 urlCheckerTask.schedule(50);
336 private static final RequestProcessor WORKER = new RequestProcessor(CustomizeRemoteIndex.class.getName(), 1, false, false);
337 private final RequestProcessor.Task urlCheckerTask = WORKER.create(new Runnable() {
340 checkingIndexURL.set(true);
341 checkingIndexURLError.set(null);
343 SwingUtilities.invokeLater(new Runnable() {
349 String urlText = checkingIndexURLContentCopy.get();
350 Collection<? extends String> subindices = null;
353 URL url = new URL(urlText);
355 if (!url.getPath().endsWith("/"))
356 url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
358 subindices = WebUtilities.requestStringArrayResponse(url.toURI().resolve("list"));
360 if (subindices.isEmpty()) {
361 checkingIndexURLError.set("Not an index.");
363 } catch (URISyntaxException ex) {
364 checkingIndexURLError.set(ex.getLocalizedMessage());
365 } catch (MalformedURLException ex) {
366 checkingIndexURLError.set(ex.getLocalizedMessage());
367 } catch (ThreadDeath td) {
369 } catch (Throwable t) {//#6541019
370 checkingIndexURLError.set("Invalid URL");
373 checkingIndexURL.set(false);
375 final Collection<? extends String> subindicesFinal = subindices;
377 SwingUtilities.invokeLater(new Runnable() {
381 if (subindicesFinal == null || subindicesFinal.isEmpty()) return;
383 DefaultComboBoxModel model = (DefaultComboBoxModel) subIndex.getModel();
384 String selected = (String) model.getSelectedItem();
386 model.removeAllElements();
388 boolean containsSelection = false;
389 Map<String, String> displayNames = new HashMap<String, String>();
391 for (String subindex : subindicesFinal) {
392 String[] subindexSplit = subindex.split(":", 2);
393 if (subindexSplit[0].equals(selected)) containsSelection = true;
394 model.addElement(subindexSplit[0]);
395 displayNames.put(subindexSplit[0], subindexSplit[1]);
398 if (containsSelection) {
399 model.setSelectedItem(selected);
402 subindexSelectionUpdated();
403 subIndex.setRenderer(new RendererImpl(displayNames));
409 private final AtomicReference<String> indexInfoURLContentCopy = new AtomicReference<String>();
410 private final AtomicReference<String> indexInfoSubIndexCopy = new AtomicReference<String>();
411 private void subindexSelectionUpdated() {
412 indexInfoURLContentCopy.set(indexURL.getText());
413 indexInfoSubIndexCopy.set((String) subIndex.getSelectedItem());
414 indexInfoTask.cancel();
415 indexInfoTask.schedule(50);
418 private final RequestProcessor.Task indexInfoTask = WORKER.create(new Runnable() {
421 String urlText = indexInfoURLContentCopy.get();
422 String subIndex = indexInfoSubIndexCopy.get();
423 IndexInfo info = null;
426 URL url = new URL(urlText);
428 if (!url.getPath().endsWith("/"))
429 url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
431 String indexInfoText = WebUtilities.requestStringResponse(url.toURI().resolve("info?path=" + WebUtilities.escapeForQuery(subIndex)));
432 info = IndexInfo.empty();
434 if (indexInfoText != null)
435 Pojson.update(info, indexInfoText);
436 } catch (URISyntaxException ex) {
437 Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
438 } catch (MalformedURLException ex) {
439 Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
442 final IndexInfo infoFinal = info;
444 SwingUtilities.invokeLater(new Runnable() {
446 if (infoFinal != null) {
447 indexInfo.setText(toDisplayText(infoFinal));
449 indexInfo.setText("");
456 private static String toDisplayText(IndexInfo info) {
457 StringBuilder sb = new StringBuilder();
459 if (info.sourceLocation != null) {
460 sb.append("Source Location: ").append(info.sourceLocation).append("\n");
462 if (info.lastUpdate >= 0) {
463 sb.append("Last Update:\t").append(DateFormat.getDateTimeInstance().format(new Date(info.lastUpdate))).append("\n");
465 if (info.totalFiles >= 0) {
466 sb.append("Indexed Files:\t").append(info.totalFiles).append("\n");
469 return sb.toString();
472 private static final class RendererImpl extends DefaultListCellRenderer {
473 private final Map<String, String> displayNames;
474 public RendererImpl(Map<String, String> displayNames) {
475 this.displayNames = displayNames;
479 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
480 return super.getListCellRendererComponent(list, displayNames.get(value), index, isSelected, cellHasFocus);