blob: ef13e49f2bfebe56553e82e1a73d95d42f5fe346 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.analysis;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.BeanInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.fileinfo.NonRecursiveFolder;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.analysis.spi.Analyzer.AnalyzerFactory;
import org.netbeans.modules.analysis.spi.Analyzer.Context;
import org.netbeans.modules.analysis.spi.Analyzer.MissingPlugin;
import org.netbeans.modules.analysis.spi.Analyzer.WarningDescription;
import org.netbeans.modules.analysis.ui.AdjustConfigurationPanel;
import org.netbeans.modules.analysis.ui.AdjustConfigurationPanel.ErrorListener;
import org.netbeans.modules.analysis.ui.ConfigurationsComboModel;
import org.netbeans.modules.refactoring.api.Scope;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotificationLineSupport;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle.Messages;
import org.openide.util.NbPreferences;
import org.openide.util.RequestProcessor;
/**
*
* @author lahvac
*/
public final class RunAnalysisPanel extends javax.swing.JPanel implements LookupListener {
private static final String COMBO_PROTOTYPE = "999999999999999999999999999999999999";
private static final RequestProcessor WORKER = new RequestProcessor(RunAnalysisPanel.class.getName(), 1, false, false);
private final JPanel progress;
private final RequiredPluginsPanel requiredPlugins;
//GuardedBy(AWT)
private Collection<? extends AnalyzerFactory> analyzers;
//GuardedBy(AWT)
private FutureWarnings analyzer2Warnings;
private final Lookup.Result<AnalyzerFactory> analyzersResult;
private final Map<String, AnalyzerAndWarning> warningId2Description = new HashMap<String, AnalyzerAndWarning>();
private final JButton runAnalysis;
//GuardedBy(AWT)
private boolean inspectionsReady;
private boolean started;
public RunAnalysisPanel(ProgressHandle handle, Lookup context, JButton runAnalysis) {
this(handle, context, runAnalysis, null);
}
public RunAnalysisPanel(ProgressHandle handle, Lookup context, JButton runAnalysis, DialogState state) {
this.runAnalysis = runAnalysis;
this.analyzersResult = Lookup.getDefault().lookupResult(AnalyzerFactory.class);
this.analyzersResult.addLookupListener(this);
initComponents();
List<ScopeDescription> scopes = new ArrayList<ScopeDescription>();
Icon currentProjectIcon = null;
NonRecursiveFolder pack = context.lookup(NonRecursiveFolder.class);
FileObject currentFile = context.lookup(FileObject.class);
DataFolder folder = context.lookup(DataFolder.class);
if (currentFile != null && currentFile.isData()) {
scopes.add(new FileScopeDescription(currentFile));
}
if (folder != null) {
scopes.add(new FolderScopeDescription(folder));
}
if (pack != null && currentFile == null) {
currentFile = pack.getFolder();
}
if (currentFile != null) {
Project p = FileOwnerQuery.getOwner(currentFile);
if (p != null) {
ProjectInformation pi = ProjectUtils.getInformation(p);
scopes.add(0, new CurrentProjectScopeDescription(p));
currentProjectIcon = pi.getIcon();
if (pack == null) {
ClassPath bootCP = ClassPath.getClassPath(currentFile, ClassPath.BOOT);
if (bootCP != null) {
final FileObject packFO = !currentFile.isFolder() ? currentFile.getParent() : currentFile;
pack = new NonRecursiveFolder() {
@Override public FileObject getFolder() {
return packFO;
}
};
}
}
}
} else {
Project selected = context.lookup(Project.class);
if (selected == null) {
SourceGroup sg = context.lookup(SourceGroup.class);
if (sg != null) {
selected = FileOwnerQuery.getOwner(sg.getRootFolder());
}
}
if (selected == null) {
DataFolder df = context.lookup(DataFolder.class);
if (df != null) {
selected = FileOwnerQuery.getOwner(df.getPrimaryFile());
}
}
if (selected != null) {
ProjectInformation pi = ProjectUtils.getInformation(selected);
scopes.add(0, new CurrentProjectScopeDescription(selected));
currentProjectIcon = pi.getIcon();
}
}
if (pack != null) {
ClassPath source = ClassPath.getClassPath(pack.getFolder(), ClassPath.SOURCE);
if (source != null) {
String packName = source.getResourceName(pack.getFolder(), '.', false);
scopes.add(1, new PackageScopeDescription(pack, packName));
}
}
scopes.add(0, new AllProjectsScopeDescription(currentProjectIcon));
scopeCombo.setModel(new DefaultComboBoxModel(scopes.toArray(new ScopeDescription[0])));
scopeCombo.setRenderer(new ScopeRenderer());
scopeCombo.setSelectedIndex(scopes.size() - 1);
GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1;
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
progress = new JPanel(new CardLayout());
progress.add(new JPanel(), "empty");
progress.add(ProgressHandleFactory.createProgressComponent(handle), "progress");
progress.add(requiredPlugins = new RequiredPluginsPanel(), "plugins");
add(progress, gridBagConstraints);
((CardLayout) progress.getLayout()).show(progress, "empty");
if (state == null) state = DialogState.load();
updateConfigurations(state);
updateEnableDisable();
setBorder(new EmptyBorder(12, 12, 12, 12));
ConfigurationsManager.getDefault().addChangeListener(new ChangeListener() {
@Override public void stateChanged(ChangeEvent e) {
resultChanged(null);
}
});
configurationCombo.addActionListener(new ActionListener() {
Object currentItem = configurationCombo.getSelectedItem();
@Override
public void actionPerformed(ActionEvent e) {
Object tempItem = configurationCombo.getSelectedItem();
if (tempItem instanceof String) {
configurationCombo.setSelectedItem(currentItem);
} else {
currentItem = tempItem;
updateEnableDisable();
}
}
});
inspectionCombo.addActionListener(new ActionListener() {
Object currentItem = inspectionCombo.getSelectedItem();
@Override
public void actionPerformed(ActionEvent e) {
Object tempItem = inspectionCombo.getSelectedItem();
if (!(tempItem instanceof AnalyzerAndWarning)) {
inspectionCombo.setSelectedItem(currentItem);
updatePlugins();
} else {
currentItem = tempItem;
}
}
});
inspectionCombo.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int direction = 1;
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
direction = 1;
break;
case KeyEvent.VK_UP:
direction = -1;
break;
}
int currentIndex = inspectionCombo.getSelectedIndex() + direction;
Object tempItem = inspectionCombo.getItemAt(currentIndex);
if (tempItem instanceof AnalyzerAndWarning) {
return;
} else {
currentIndex += direction;
}
Object nextItem = inspectionCombo.getItemAt(currentIndex);
while (!(nextItem instanceof AnalyzerAndWarning)) {
currentIndex += direction;
nextItem = inspectionCombo.getItemAt(currentIndex);
if (nextItem == null) {
return;
}
}
inspectionCombo.setSelectedItem((AnalyzerAndWarning) nextItem);
e.consume();
}
});
if (state != null && state.scope != null) {
for (int i = 0; i < scopeCombo.getItemCount(); i++) {
ScopeDescription sd = (ScopeDescription)scopeCombo.getItemAt(i);
if (sd != null && sd.getId().equals(state.scope)) {
scopeCombo.setSelectedIndex(i);
break;
}
}
}
}
void started() {
started = true;
((CardLayout) progress.getLayout()).show(progress, "progress");
progress.invalidate();
//disable all elements in the dialog:
List<JComponent> todo = new LinkedList<JComponent>();
todo.add(this);
while (!todo.isEmpty()) {
JComponent c = todo.remove(0);
if (c == progress) continue;
c.setEnabled(false);
for (Component child : c.getComponents()) {
if (child instanceof JComponent) todo.add((JComponent) child);
}
}
}
@Messages({"LBL_Predefined=Predefined", "LBL_Custom=Custom", "LBL_PleaseWait=Computing..."})
public void updateConfigurations(final DialogState state) {
analyzers = analyzersResult.allInstances();
Object selectedConfiguration = null;
DefaultComboBoxModel configurationModel = new DefaultComboBoxModel();
configurationModel.addElement(Bundle.LBL_Predefined());
configurationModel.addElement(null);
for (AnalyzerFactory analyzer : analyzers) {
if (SPIAccessor.ACCESSOR.getAnalyzerId(analyzer).equals(state.selectedAnalyzer)) {
selectedConfiguration = analyzer;
}
configurationModel.addElement(analyzer);
}
configurationModel.addElement(Bundle.LBL_Custom());
for (Configuration c : ConfigurationsManager.getDefault().getConfigurations()) {
if (c.id().equals(state.selectedConfiguration)) {
selectedConfiguration = c;
}
configurationModel.addElement(c);
}
configurationCombo.setModel(configurationModel);
configurationCombo.setSelectedItem(selectedConfiguration);
configurationRadio.setSelected(state.configurationsSelected);
configurationCombo.setRenderer(new ConfigurationRenderer(true));
DefaultComboBoxModel inspectionModel = new DefaultComboBoxModel();
inspectionModel.addElement(Bundle.LBL_PleaseWait());
inspectionCombo.setModel(inspectionModel);
inspectionCombo.setRenderer(new InspectionRenderer());
inspectionCombo.setSelectedItem(0);
singleInspectionRadio.setSelected(!state.configurationsSelected);
updatePlugins();
final Collection<? extends AnalyzerFactory> analyzersCopy = new ArrayList<AnalyzerFactory>(analyzers);
inspectionsReady = false;
analyzer2Warnings = new FutureWarnings();
WORKER.post(new Runnable() {
@Override public void run() {
final Map<AnalyzerFactory, Iterable<? extends WarningDescription>> analyzer2Warnings = new HashMap<AnalyzerFactory, Iterable<? extends WarningDescription>>();
for (AnalyzerFactory a : analyzersCopy) {
List<WarningDescription> warnings = new ArrayList<WarningDescription>();
for (WarningDescription wd : a.getWarnings()) {
warnings.add(wd);
}
analyzer2Warnings.put(a, warnings);
}
final Map<AnalyzerFactory, Map<String, WarningDescription>> analyzer2Id2DescriptionVal = computeAnalyzerId2Description(analyzer2Warnings);
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
RunAnalysisPanel.this.analyzer2Warnings.set(analyzer2Id2DescriptionVal);
fillInspectionCombo(state, analyzer2Warnings);
inspectionsReady = true;
updatePlugins();
}
});
}
});
}
private void fillInspectionCombo(DialogState state, Map<? extends AnalyzerFactory, Iterable<? extends WarningDescription>> analyzer2Warnings) {
DefaultComboBoxModel inspectionModel = new DefaultComboBoxModel();
AnalyzerAndWarning firstInspection = null;
AnalyzerAndWarning preselectInspection = null;
for (Entry<? extends AnalyzerFactory, Iterable<? extends WarningDescription>> e : analyzer2Warnings.entrySet()) {
inspectionModel.addElement(SPIAccessor.ACCESSOR.getAnalyzerDisplayName(e.getKey()));
Map<String, Collection<WarningDescription>> cat2Warnings = new TreeMap<String, Collection<WarningDescription>>();
for (WarningDescription wd : e.getValue()) {
String cat = SPIAccessor.ACCESSOR.getWarningCategoryDisplayName(wd); //TODO: should be based on the id rather than on the display name
Collection<WarningDescription> warnings = cat2Warnings.get(cat);
if (warnings == null) {
cat2Warnings.put(cat, warnings = new TreeSet<WarningDescription>(new Comparator<WarningDescription>() {
@Override public int compare(WarningDescription o1, WarningDescription o2) {
return SPIAccessor.ACCESSOR.getWarningDisplayName(o1).compareToIgnoreCase(SPIAccessor.ACCESSOR.getWarningDisplayName(o2));
}
}));
}
warnings.add(wd);
}
for (Entry<String, Collection<WarningDescription>> catE : cat2Warnings.entrySet()) {
inspectionModel.addElement(" " + catE.getKey());
for (WarningDescription wd : catE.getValue()) {
AnalyzerAndWarning aaw = new AnalyzerAndWarning(e.getKey(), wd);
inspectionModel.addElement(aaw);
warningId2Description.put(SPIAccessor.ACCESSOR.getWarningId(wd), aaw);
if (firstInspection == null) firstInspection = aaw;
if (SPIAccessor.ACCESSOR.getWarningId(wd).equals(state.selectedInspection)) {
preselectInspection = aaw;
}
}
}
}
inspectionCombo.setModel(inspectionModel);
inspectionCombo.setSelectedItem(preselectInspection != null ? preselectInspection : firstInspection);
}
private void updatePlugins() {
if (started) return ;
Collection<? extends AnalyzerFactory> toRun;
if (singleInspectionRadio.isSelected()) {
if (!inspectionsReady) {
runAnalysis.setEnabled(false);
return ;
}
Object selectedInspection = inspectionCombo.getSelectedItem();
if (selectedInspection instanceof AnalyzerAndWarning) {
toRun = Collections.singleton(((AnalyzerAndWarning) selectedInspection).analyzer);
} else {
toRun = Collections.emptyList();
}
} else {
if (!(configurationCombo.getSelectedItem() instanceof AnalyzerFactory)) {
toRun = analyzers;
} else {
toRun = Collections.singleton((AnalyzerFactory) configurationCombo.getSelectedItem());
}
}
Set<MissingPlugin> plugins = new HashSet<MissingPlugin>();
boolean someOk = false;
for (AnalyzerFactory a : toRun) {
Configuration configuration = getConfiguration();
Preferences settings = configuration != null ? configuration.getPreferences().node(SPIAccessor.ACCESSOR.getAnalyzerId(a)) : null;
Context ctx = SPIAccessor.ACCESSOR.createContext(getSelectedScope(new AtomicBoolean(false)), settings, null, null, -1, -1);
Collection<? extends MissingPlugin> req = a.requiredPlugins(ctx);
plugins.addAll(req);
someOk |= req.isEmpty();
}
if (plugins.isEmpty()) {
((CardLayout) progress.getLayout()).show(progress, "empty");
} else {
requiredPlugins.setRequiredPlugins(plugins, !someOk);
((CardLayout) progress.getLayout()).show(progress, "plugins");
}
runAnalysis.setEnabled(someOk);
}
public Scope getSelectedScope(AtomicBoolean cancel) {
return ((ScopeDescription) scopeCombo.getSelectedItem()).getScope(cancel);
}
public AnalyzerFactory getSelectedAnalyzer() {
if (singleInspectionRadio.isSelected()) {
Object singleInspection = inspectionCombo.getSelectedItem();
if (singleInspection instanceof AnalyzerAndWarning) {
return ((AnalyzerAndWarning) singleInspection).analyzer;
}
return null;
}
if (!(configurationCombo.getSelectedItem() instanceof AnalyzerFactory)) return null;
return (AnalyzerFactory) configurationCombo.getSelectedItem();
}
public Configuration getConfiguration() {
if (inspectionCombo.isEnabled()) return ConfigurationsManager.getDefault().getTemporaryConfiguration();
Object selected = configurationCombo.getSelectedItem();
if (selected instanceof Configuration) return (Configuration) selected;
else return null;
}
public Collection<? extends AnalyzerFactory> getAnalyzers() {
return analyzers;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
radioButtons = new javax.swing.ButtonGroup();
javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
scopeCombo = new javax.swing.JComboBox();
javax.swing.JLabel jLabel2 = new javax.swing.JLabel();
configurationCombo = new javax.swing.JComboBox();
manage = new javax.swing.JButton();
configurationRadio = new javax.swing.JRadioButton();
singleInspectionRadio = new javax.swing.JRadioButton();
inspectionCombo = new javax.swing.JComboBox();
browse = new javax.swing.JButton();
javax.swing.JPanel emptyPanel = new javax.swing.JPanel();
setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.jLabel1.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.ABOVE_BASELINE_LEADING;
add(jLabel1, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.ABOVE_BASELINE_LEADING;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
add(scopeCombo, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.jLabel2.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.ABOVE_BASELINE_LEADING;
gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
add(jLabel2, gridBagConstraints);
configurationCombo.setPrototypeDisplayValue(COMBO_PROTOTYPE);
configurationCombo.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configurationComboActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.ABOVE_BASELINE_LEADING;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(configurationCombo, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(manage, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.manage.text")); // NOI18N
manage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
manageActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(manage, gridBagConstraints);
radioButtons.add(configurationRadio);
org.openide.awt.Mnemonics.setLocalizedText(configurationRadio, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.configurationRadio.text")); // NOI18N
configurationRadio.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configurationRadioActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(configurationRadio, gridBagConstraints);
radioButtons.add(singleInspectionRadio);
org.openide.awt.Mnemonics.setLocalizedText(singleInspectionRadio, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.singleInspectionRadio.text")); // NOI18N
singleInspectionRadio.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
singleInspectionRadioActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE_LEADING;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(singleInspectionRadio, gridBagConstraints);
inspectionCombo.setPrototypeDisplayValue(COMBO_PROTOTYPE);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(inspectionCombo, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(browse, org.openide.util.NbBundle.getMessage(RunAnalysisPanel.class, "RunAnalysisPanel.browse.text")); // NOI18N
browse.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE;
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
add(browse, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weighty = 1.0;
add(emptyPanel, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
private void configurationComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configurationComboActionPerformed
updatePlugins();
}//GEN-LAST:event_configurationComboActionPerformed
private AdjustConfigurationPanel showConfigurationPanel(AnalyzerFactory preselectedAnalyzer, String preselected, Configuration configurationToSelect) {
final NotificationLineSupport[] nls = new NotificationLineSupport[1];
final DialogDescriptor[] dd = new DialogDescriptor[1];
ErrorListener errorListener = new ErrorListener() {
@Override public void setError(String error) {
nls[0].setErrorMessage(error);
dd[0].setValid(error == null);
}
};
AdjustConfigurationPanel panel = new AdjustConfigurationPanel(analyzers, preselectedAnalyzer, preselected, configurationToSelect, errorListener);
panel.setPreferredSize(new Dimension(700, 300));
DialogDescriptor nd = new DialogDescriptor(panel, Bundle.LBL_Configurations(), true, NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.OK_OPTION, null);
nls[0] = nd.createNotificationLineSupport();
dd[0] = nd;
if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.OK_OPTION) {
return panel;
}
return null;
}
@Messages("LBL_Configurations=Configurations")
private void manageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageActionPerformed
AdjustConfigurationPanel panel = showConfigurationPanel(null, null, (Configuration) configurationCombo.getSelectedItem());
if (panel != null) {
panel.save();
configurationCombo.setSelectedItem(panel.getSelectedConfiguration());
}
}//GEN-LAST:event_manageActionPerformed
private void configurationRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configurationRadioActionPerformed
updateEnableDisable();
}//GEN-LAST:event_configurationRadioActionPerformed
private void singleInspectionRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_singleInspectionRadioActionPerformed
updateEnableDisable();
}//GEN-LAST:event_singleInspectionRadioActionPerformed
@Messages("LBL_Browse=Browse Inspections")
private void browseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseActionPerformed
Object selectedInspection = inspectionCombo.getSelectedItem();
AnalyzerFactory analyzerToSelect;
String warningToSelect;
if (selectedInspection instanceof AnalyzerAndWarning) {
analyzerToSelect = ((AnalyzerAndWarning) selectedInspection).analyzer;
warningToSelect = SPIAccessor.ACCESSOR.getWarningId(((AnalyzerAndWarning) selectedInspection).wd);
} else {
analyzerToSelect = null;
warningToSelect = "";
}
AdjustConfigurationPanel panel = showConfigurationPanel(analyzerToSelect, warningToSelect, null);
if (panel != null) {
inspectionCombo.setSelectedItem(warningId2Description.get(panel.getIdToRun()));
}
}//GEN-LAST:event_browseActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browse;
private javax.swing.JComboBox configurationCombo;
private javax.swing.JRadioButton configurationRadio;
private javax.swing.JComboBox inspectionCombo;
private javax.swing.JButton manage;
private javax.swing.ButtonGroup radioButtons;
private javax.swing.JComboBox scopeCombo;
private javax.swing.JRadioButton singleInspectionRadio;
// End of variables declaration//GEN-END:variables
private void updateEnableDisable() {
if (started) return ;
boolean configuration = configurationRadio.isSelected();
configurationCombo.setEnabled(configuration);
manage.setEnabled(configuration && configurationCombo.getSelectedItem() instanceof Configuration);
inspectionCombo.setEnabled(!configuration);
browse.setEnabled(!configuration);
updatePlugins();
}
String getSingleWarningId() {
return inspectionCombo.isEnabled() ? SPIAccessor.ACCESSOR.getWarningId(((AnalyzerAndWarning) inspectionCombo.getSelectedItem()).wd) : null;
}
@Override
public void resultChanged(LookupEvent ev) {
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
updateConfigurations(getDialogState());
}
});
}
public DialogState getDialogState() {
Object selectedConfiguration = configurationCombo.getSelectedItem();
Object selectedInspection = inspectionCombo.getSelectedItem();
return new DialogState(configurationRadio.isSelected(),
selectedConfiguration instanceof AnalyzerFactory ? SPIAccessor.ACCESSOR.getAnalyzerId((AnalyzerFactory) selectedConfiguration) : null,
selectedConfiguration instanceof Configuration ? ((Configuration) selectedConfiguration).id() : null,
selectedInspection instanceof AnalyzerAndWarning ? SPIAccessor.ACCESSOR.getWarningId(((AnalyzerAndWarning) selectedInspection).wd) : null,
((ScopeDescription) scopeCombo.getSelectedItem()).getId());
}
FutureWarnings getAnalyzerId2Description() {
return analyzer2Warnings;
}
private static Map<AnalyzerFactory, Map<String, WarningDescription>> computeAnalyzerId2Description(Map<? extends AnalyzerFactory, Iterable<? extends WarningDescription>> analyzer2Warnings) {
Map<AnalyzerFactory, Map<String, WarningDescription>> result = new HashMap<AnalyzerFactory, Map<String, WarningDescription>>();
for (Entry<? extends AnalyzerFactory, Iterable<? extends WarningDescription>> e : analyzer2Warnings.entrySet()) {
Map<String, WarningDescription> perAnalyzer = new HashMap<String, WarningDescription>();
result.put(e.getKey(), perAnalyzer);
for (WarningDescription wd : e.getValue()) {
perAnalyzer.put(SPIAccessor.ACCESSOR.getWarningId(wd), wd);
}
}
return result;
}
public static final class ConfigurationRenderer extends DefaultListCellRenderer {
private final boolean indent;
public ConfigurationRenderer(boolean indent) {
this.indent = indent;
}
@Messages({"LBL_RunAllAnalyzers=All Analyzers", "# {0} - the analyzer that should be run", "LBL_RunAnalyzer={0}"})
@Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value == null) {
value = Bundle.LBL_RunAllAnalyzers();
} else if (value instanceof AnalyzerFactory) {
value = Bundle.LBL_RunAnalyzer(SPIAccessor.ACCESSOR.getAnalyzerDisplayName((AnalyzerFactory) value));
} else if (value instanceof Configuration) {
value = ((Configuration) value).getDisplayName();
} else if (value instanceof String) {
setFont(getFont().deriveFont(Font.ITALIC));
setText((String) value);
setEnabled(false);
setBackground(list.getBackground());
setForeground(UIManager.getColor("Label.disabledForeground"));
return this;
}
if (index == list.getModel().getSize()-5 && list.getModel() instanceof ConfigurationsComboModel && ((ConfigurationsComboModel) list.getModel()).canModify()) {
setBorder(new Separator(list.getForeground()));
} else {
setBorder(null);
}
return super.getListCellRendererComponent(list, (indent ? " " : "") + value, index, isSelected, cellHasFocus);
}
}
private static final class InspectionRenderer extends DefaultListCellRenderer {
@Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof AnalyzerAndWarning) {
value = " " + SPIAccessor.ACCESSOR.getWarningDisplayName(((AnalyzerAndWarning) value).wd);
} else if (value instanceof String) {
setFont(getFont().deriveFont(Font.ITALIC));
setText((String) value);
setEnabled(false);
setBackground(list.getBackground());
setForeground(UIManager.getColor("Label.disabledForeground"));
return this;
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
private interface ScopeDescription {
public String getDisplayName();
public Icon getIcon();
public Scope getScope(AtomicBoolean cancel);
public String getId();
}
private static final class AllProjectsScopeDescription implements ScopeDescription {
private final Icon icon;
public AllProjectsScopeDescription(Icon icon) {
this.icon = icon;
}
@Override
@Messages("DN_OpenProjects=Open Projects")
public String getDisplayName() {
return Bundle.DN_OpenProjects();
}
@Override
public Icon getIcon() {
return icon;
}
@Override
public Scope getScope(AtomicBoolean cancel) {
Map<Project, Map<FileObject, ClassPath>> projects2RegisteredContent = RunAnalysis.projects2RegisteredContent(cancel);
if (cancel.get()) return null;
Scope target = Scope.create(null, null, null);
for (Project p : OpenProjects.getDefault().getOpenProjects()) {
if (cancel.get()) return null;
target = RunAnalysis.addProjectToScope(p, target, cancel, projects2RegisteredContent);
}
return target;
}
public String getId() {
return "*allProjects"; // NOI18N
}
}
private static final class CurrentProjectScopeDescription implements ScopeDescription {
private final Project project;
public CurrentProjectScopeDescription(Project project) {
this.project = project;
}
@Override
@Messages({"# {0} - project display name", "DN_CurrentProject=Current Project ({0})"})
public String getDisplayName() {
return Bundle.DN_CurrentProject(ProjectUtils.getInformation(project).getDisplayName());
}
@Override
public Icon getIcon() {
return ProjectUtils.getInformation(project).getIcon();
}
@Override
public Scope getScope(AtomicBoolean cancel) {
Map<Project, Map<FileObject, ClassPath>> projects2RegisteredContent = RunAnalysis.projects2RegisteredContent(cancel);
if (cancel.get()) return null;
return RunAnalysis.addProjectToScope(project, Scope.create(null, null, null), cancel, projects2RegisteredContent);
}
public String getId() {
return "*currentProject"; // NOI18N
}
}
private static final class PackageScopeDescription implements ScopeDescription {
private final NonRecursiveFolder pack;
private final String packName;
public PackageScopeDescription(NonRecursiveFolder pack, String packName) {
this.pack = pack;
this.packName = packName;
}
@Override
@Messages({"# {0} - package display name", "DN_CurrentPackage=Current Package ({0})"})
public String getDisplayName() {
return Bundle.DN_CurrentPackage(packName);
}
@Override
public Icon getIcon() {
return ImageUtilities.loadImageIcon("org/netbeans/modules/analysis/ui/resources/package.gif", false);
}
@Override
public Scope getScope(AtomicBoolean cancel) {
return Scope.create(null, Collections.singletonList(pack), null);
}
public String getId() {
return "*currentPackage"; // NOI18N
}
}
private static final class FolderScopeDescription implements ScopeDescription {
private final DataFolder folder;
public FolderScopeDescription(DataFolder folder) {
this.folder = folder;
}
@Override
@Messages({"# {0} - folder display name", "DN_CurrentFolder=Current Folder ({0})"})
public String getDisplayName() {
return Bundle.DN_CurrentFolder(folder.getName());
}
@Override
public Icon getIcon() {
return ImageUtilities.image2Icon(folder.getNodeDelegate().getIcon(1));
}
@Override
public Scope getScope(AtomicBoolean cancel) {
return Scope.create(null, null, folder.files());
}
public String getId() {
return "*currentFolder"; // NOI18N
}
}
private static final class FileScopeDescription implements ScopeDescription {
private static final Logger LOG = Logger.getLogger(FileScopeDescription.class.getName());
private final FileObject file;
public FileScopeDescription(FileObject file) {
this.file = file;
}
@Override
@Messages({"# {0} - file display name", "DN_CurrentFile=Current File ({0})"})
public String getDisplayName() {
return Bundle.DN_CurrentFile(file.getNameExt());
}
@Override
public Icon getIcon() {
try {
DataObject d = DataObject.find(file);
Node n = d.getNodeDelegate();
return ImageUtilities.image2Icon(n.getIcon(BeanInfo.ICON_COLOR_16x16));
} catch (DataObjectNotFoundException ex) {
LOG.log(Level.FINE, null, ex);
return null;
}
}
@Override
public Scope getScope(AtomicBoolean cancel) {
return Scope.create(null, null, Collections.singletonList(file));
}
public String getId() {
return "*currentFile";
}
}
private static final class ScopeRenderer extends DefaultListCellRenderer {
@Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof ScopeDescription) {
ScopeDescription sd = (ScopeDescription) value;
try {
return super.getListCellRendererComponent(list, sd.getDisplayName(), index, isSelected, cellHasFocus);
} finally {
setIcon(sd.getIcon());
}
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
private static class Separator implements Border {
private Color fgColor;
Separator(Color color) {
fgColor = color;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics gr = g.create();
if (gr != null) {
try {
gr.translate(x, y);
gr.setColor(fgColor);
gr.drawLine(0, height - 1, width - 1, height - 1);
} finally {
gr.dispose();
}
}
}
public boolean isBorderOpaque() {
return true;
}
public Insets getBorderInsets(Component c) {
return new Insets(0, 0, 1, 0);
}
}
private static final class AnalyzerAndWarning {
private final AnalyzerFactory analyzer;
private final WarningDescription wd;
public AnalyzerAndWarning(AnalyzerFactory analyzer, WarningDescription wd) {
this.analyzer = analyzer;
this.wd = wd;
}
}
public static final class DialogState {
private final boolean configurationsSelected;
private final String selectedAnalyzer;
private final String selectedConfiguration;
private final String selectedInspection;
private final String scope;
private DialogState(boolean configurationsSelected, String selectedAnalyzer, String selectedConfiguration, String selectedInspection, String scope) {
this.configurationsSelected = configurationsSelected;
this.selectedAnalyzer = selectedAnalyzer;
this.selectedConfiguration = selectedConfiguration;
this.selectedInspection = selectedInspection;
this.scope = scope;
}
public void save() {
Preferences prefs = NbPreferences.forModule(RunAnalysisPanel.class).node("RunAnalysisPanel");
prefs.putBoolean("configurationsSelected", configurationsSelected);
if (selectedAnalyzer != null)
prefs.put("selectedAnalyzer", selectedAnalyzer);
else
prefs.remove("selectedAnalyzer");
if (selectedConfiguration != null)
prefs.put("selectedConfiguration", selectedConfiguration);
else
prefs.remove("selectedConfiguration");
if (selectedInspection != null)
prefs.put("selectedInspection", selectedInspection);
else
prefs.remove("selectedInspection");
}
private static DialogState load() {
Preferences prefs = NbPreferences.forModule(RunAnalysisPanel.class).node("RunAnalysisPanel");
return new DialogState(prefs.getBoolean("configurationsSelected", true),
prefs.get("selectedAnalyzer", null),
prefs.get("selectedConfiguration", null),
prefs.get("selectedInspection", null),
null);
}
public static DialogState from(WarningDescription wd) {
return new DialogState(false, null, null, SPIAccessor.ACCESSOR.getWarningId(wd), null);
}
}
public static class FutureWarnings {
private Map<AnalyzerFactory, Map<String, WarningDescription>> result;
public synchronized boolean isDone() {
return result != null;
}
public synchronized Map<AnalyzerFactory, Map<String, WarningDescription>> get() {
while (result == null) {
try {
wait();
} catch (InterruptedException ex) {
//Should not be happening, hopefully:
Logger.getLogger(RunAnalysisPanel.class.getName()).log(Level.FINE, null, ex);
}
}
return result;
}
synchronized void set(Map<AnalyzerFactory, Map<String, WarningDescription>> value) {
result = value;
notifyAll();
}
}
}