Index: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.form =================================================================== RCS file: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.form diff -N src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.form --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.form 14 Jun 2007 13:03:17 -0000 @@ -0,0 +1,78 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.java =================================================================== RCS file: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.java diff -N src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceAlertPanel.java 14 Jun 2007 13:03:17 -0000 @@ -0,0 +1,97 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.j2ee.common.ui; + +import javax.swing.JPanel; +import org.openide.util.NbBundle; + +/** + * Broken/missing datasource alert panel. + * + * PLEASE NOTE! This is just a temporary solution. BrokenReferencesSupport from + * the java project support currently does not allow to plug in a check for missing + * datasources. Once BrokenReferencesSupport will support it, this class should be + * removed. + */ +public class BrokenDatasourceAlertPanel extends JPanel { + + public BrokenDatasourceAlertPanel() { + initComponents(); + notAgain.setSelected(!J2EEUISettings.getDefault().isShowAgainBrokenDatasourceAlert()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + notAgain = new javax.swing.JCheckBox(); + message = new javax.swing.JLabel(); + + setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(notAgain, org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "MSG_Broken_Datasources_Again")); // NOI18N + notAgain.setMargin(new java.awt.Insets(0, 0, 0, 0)); + notAgain.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + notAgainActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 11, 0, 0); + add(notAgain, gridBagConstraints); + notAgain.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSN_BrokenDatasourcesAlertPanel_notAgain")); // NOI18N + notAgain.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSD_BrokenDatasourcesAlertPanel_notAgain")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(message, org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "MSG_Broken_Datasources")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(11, 11, 0, 0); + add(message, gridBagConstraints); + message.getAccessibleContext().setAccessibleName(NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSN_BrokenDatasourcesAlertPanel")); // NOI18N + message.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSD_BrokenDatasourcesAlertPanel")); // NOI18N + + getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSN_BrokenDatasourceAlertPanel")); // NOI18N + getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "ACSD_BrokenDatasourcesAlertPanel")); // NOI18N + }// //GEN-END:initComponents + + private void notAgainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_notAgainActionPerformed + J2EEUISettings.getDefault().setShowAgainBrokenDatasourceAlert(!notAgain.isSelected()); + }//GEN-LAST:event_notAgainActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel message; + private javax.swing.JCheckBox notAgain; + // End of variables declaration//GEN-END:variables + +} Index: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceSupport.java =================================================================== RCS file: src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceSupport.java diff -N src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceSupport.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/netbeans/modules/j2ee/common/ui/BrokenDatasourceSupport.java 14 Jun 2007 13:03:17 -0000 @@ -0,0 +1,200 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.j2ee.common.ui; + +import java.awt.Dialog; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import javax.swing.JButton; +import javax.swing.SwingUtilities; +import org.netbeans.api.db.explorer.ConnectionManager; +import org.netbeans.api.db.explorer.DatabaseConnection; +import org.netbeans.api.project.Project; +import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException; +import org.netbeans.modules.j2ee.deployment.common.api.Datasource; +import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; + +/** + * Support for managing broken/missing Databases. + * + * PLEASE NOTE! This is just a temporary solution. BrokenReferencesSupport from + * the java project support currently does not allow to plug in a check for missing + * Databases. Once BrokenReferencesSupport will support it, this class should be + * removed. + */ +public class BrokenDatasourceSupport { + + /** Last time in ms when the Broken References alert was shown. */ + private static long brokenAlertLastTime = 0; + + /** Is Broken References alert shown now? */ + private static boolean brokenAlertShown = false; + + /** Timeout within which request to show alert will be ignored. */ + private static int BROKEN_ALERT_TIMEOUT = 1000; + + private BrokenDatasourceSupport() {} + + /** + * Shows UI customizer which gives users chance to fix encountered problems, + * i.e. choose appropriate data source. + * + * @param project + * @return selected database connection. Might be null. + */ + public static String fixDatasources(final Project project) { + return MissingDatabaseConnectionWarning.selectDatasources( + NbBundle.getMessage(BrokenDatasourceSupport.class,"LBL_Resolve_Missing_Datasources_Title"),org.openide.util.NbBundle.getMessage(BrokenDatasourceSupport.class, "ACSD_Resolve_Missing_Datasources"), project); // NOI18N + } + + /** + * Show alert message box informing user that a project has missing + * database connections. This method can be safely called from any thread, e.g. during + * the project opening, and it will take care about showing message box only + * once for several subsequent calls during a timeout. + * The alert box has also "show this warning again" check box. + */ + public static synchronized void showAlert() { + // Do not show alert if it is already shown or if it was shown + // in last BROKEN_ALERT_TIMEOUT milliseconds or if user do not wish it. + if (brokenAlertShown + || brokenAlertLastTime+BROKEN_ALERT_TIMEOUT > System.currentTimeMillis() + || !J2EEUISettings.getDefault().isShowAgainBrokenDatasourceAlert()) { + return; + } + + if (brokenAlertShown + || brokenAlertLastTime+BROKEN_ALERT_TIMEOUT > System.currentTimeMillis()) { + return; + } + + brokenAlertShown = true; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + BrokenDatasourceAlertPanel alert = new BrokenDatasourceAlertPanel(); + JButton close = new JButton( + NbBundle.getMessage(BrokenDatasourceSupport.class, "LBL_BrokenDatasourcesCustomizer_Close")); + close.getAccessibleContext().setAccessibleDescription( + NbBundle.getMessage(BrokenDatasourceSupport.class, "ACSD_BrokenDatasourcesCustomizer_Close")); + DialogDescriptor dd = new DialogDescriptor( + alert, + NbBundle.getMessage(BrokenDatasourceAlertPanel.class, "MSG_Broken_Datasources_Title"), + true, + new Object[] {close}, + close, + DialogDescriptor.DEFAULT_ALIGN, + null, + null); + dd.setMessageType(DialogDescriptor.WARNING_MESSAGE); + Dialog dlg = DialogDisplayer.getDefault().createDialog(dd); + dlg.setVisible(true); + } finally { + synchronized (BrokenDatasourceSupport.class) { + brokenAlertLastTime = System.currentTimeMillis(); + brokenAlertShown = false; + } + } + } + }); + } + + + /** + * Returns set of broken datasources + * + * @param project + * @return Set returns a set of data sources that don't have corresponding database connections + */ + public static Set getBrokenDatasources(Project project) { + J2eeModuleProvider jmp = + (J2eeModuleProvider)project.getLookup().lookup(J2eeModuleProvider.class); + + Set dss = null; + try { + dss = jmp.getModuleDatasources(); + } catch (ConfigurationException e) { + dss = new HashSet(); + } + + Set brokenDatasources = new HashSet(); + Iterator it = dss.iterator(); + while (it.hasNext()) { + Datasource ds = (Datasource)it.next(); + if(!isFound(ds)){ + brokenDatasources.add(ds); + } + } + + return brokenDatasources; + } + + private static boolean isFound(Datasource ds) { + boolean found = false; + String url = ds.getUrl(); + String username = ds.getUsername(); + DatabaseConnection[] dbConns = ConnectionManager.getDefault().getConnections(); + for(int i=0; i MSG_Broken_Server_Again=&Do not show this message again +# BrokenDataSourceAlertPanel +ACSN_BrokenDatasourcesAlertPanel=Broken Data Sources Panel +ACSD_BrokenDatasourcesAlertPanel=N/A +ACSN_BrokenDatasourcesAlertPanel_notAgain=Do not show this message again +ACSD_BrokenDatasourcesAlertPanel_notAgain=N/A +MSG_Broken_Datasources=One or more projects use database connections that have not been registered.
\ + Right-click the project in the Projects window and choose
Resolve Data Source Problem \ + to help register database connections. +MSG_Broken_Datasources_Again=&Do not show this message again + # NoSelectedServerWarning LBL_NoSuitableServerWarning_jLabel2=The problem cannot be resolved because there is no \ suitable server instance at the moment. Please add a suitable server instance in \ @@ -48,3 +65,12 @@ LBL_AddServer=&Add Server... ACSN_AddServer=Add Server Button ACSD_AddServer=N/A +LBL_SelectDatasource=To resolve, select a Data Source name below then click Add Connection. +LBL_MissingDatabaseConnectionWarning=Database Connections for the Data Sources referenced in this project could not be located. +LBL_AddDatabaseConnection=&Add Connection... +ACSN_BrokenDatasourceAlertPanel=Broken Data Sources Panel +ACSD_AddDatabaseConnection=N/A + +ACSN_AddDatabaseConnection=Add Database Connection + +LBL_NoSuitableDatabaseConnectionWarning_jLabel2=LBL_MissingDatabaseConnectionWarning Index: src/org/netbeans/modules/j2ee/common/ui/J2EEUISettings.java =================================================================== RCS file: /cvs/j2ee/utilities/src/org/netbeans/modules/j2ee/common/ui/J2EEUISettings.java,v retrieving revision 1.3 diff -u -r1.3 J2EEUISettings.java --- src/org/netbeans/modules/j2ee/common/ui/J2EEUISettings.java 1 Nov 2006 15:26:12 -0000 1.3 +++ src/org/netbeans/modules/j2ee/common/ui/J2EEUISettings.java 14 Jun 2007 13:03:17 -0000 @@ -26,6 +26,7 @@ private static final J2EEUISettings INSTANCE = new J2EEUISettings(); private static final String SHOW_AGAIN_BROKEN_REF_ALERT = "showAgainBrokenRefAlert"; // NOI18N private static final String SHOW_AGAIN_BROKEN_SERVER_ALERT = "showAgainBrokenServerAlert"; // NOI18N + private static final String SHOW_AGAIN_BROKEN_DATASOURCE_ALERT = "showAgainBrokenDatasourceAlert"; // NOI18N public String displayName() { return "J2EEUISettings"; // NOI18N (not shown in UI) @@ -50,6 +51,15 @@ public void setShowAgainBrokenServerAlert(boolean again) { getPreferences().putBoolean(SHOW_AGAIN_BROKEN_SERVER_ALERT, again); } + + public boolean isShowAgainBrokenDatasourceAlert() { + return getPreferences().getBoolean(SHOW_AGAIN_BROKEN_DATASOURCE_ALERT, true); + } + + public void setShowAgainBrokenDatasourceAlert(boolean again) { + getPreferences().putBoolean(SHOW_AGAIN_BROKEN_DATASOURCE_ALERT, again); + } + public static J2EEUISettings getDefault() { return INSTANCE; Index: src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.form =================================================================== RCS file: src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.form diff -N src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.form --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.form 14 Jun 2007 13:03:17 -0000 @@ -0,0 +1,104 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.java =================================================================== RCS file: src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.java diff -N src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/netbeans/modules/j2ee/common/ui/MissingDatabaseConnectionWarning.java 14 Jun 2007 13:03:18 -0000 @@ -0,0 +1,392 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.j2ee.common.ui; + +import java.awt.Component; +import java.awt.Dialog; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Iterator; +import java.util.Set; +import javax.swing.AbstractListModel; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import org.netbeans.api.db.explorer.ConnectionListener; +import org.netbeans.api.db.explorer.ConnectionManager; +import org.netbeans.api.db.explorer.JDBCDriver; +import org.netbeans.api.db.explorer.JDBCDriverManager; +import org.netbeans.api.project.Project; +import org.netbeans.modules.j2ee.deployment.common.api.Datasource; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; + +/** + * Displays a list of datasources for which database connections are not registered and helps the user to register + * database connections needed by the project's datasource to resolve this problem. + * + * @author Pavel Buzek, John Baker + */ +public final class MissingDatabaseConnectionWarning extends JPanel { + public static final String OK_ENABLED = "ok_enabled"; //NOI18N + private static Dialog dlg = null; + private final Border scrollPaneBorder; + private Project project; + private static RequestProcessor.Task task = null; + + private MissingDatabaseConnectionWarning(Project project) { + initComponents(); + // add MainClassChooser + this.project = project; + datasourceList.setModel(new DatasourceListModel()); + scrollPaneBorder = jScrollPane2.getBorder(); + initDatasourceList(); + } + + private void initDatasourceList() { + datasourceList.setCellRenderer(new DatasourceRenderer()); + datasourceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + datasourceList.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + boolean enabled = !datasourceList.isSelectionEmpty(); + if (!enabled) { + getDlg().dispose(); + } + } + } + ); + } + + /** + * Show the "Resolve Data Sources" dialog and let the user choose a datasource from + * the list. + * + * @param title dialog title + * @param description dialog accessible description + * @param project + * @return selected datasource or null + * + */ + public static String selectDatasources(String title, String description, Project project) { + MissingDatabaseConnectionWarning panel = new MissingDatabaseConnectionWarning(project); + Object[] options = new Object[] { + DialogDescriptor.OK_OPTION, + DialogDescriptor.CLOSED_OPTION + }; + final DialogDescriptor desc = new DialogDescriptor(panel, title, true, options, + DialogDescriptor.OK_OPTION, DialogDescriptor.DEFAULT_ALIGN, null, null); + desc.setMessageType(DialogDescriptor.WARNING_MESSAGE); + setDlg(null); + try { + setDlg(DialogDisplayer.getDefault().createDialog(desc)); + dlg.getAccessibleContext().setAccessibleDescription(description); + panel.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(MissingDatabaseConnectionWarning.OK_ENABLED)) { + Object newvalue = evt.getNewValue(); + if ((newvalue != null) && (newvalue instanceof Boolean)) { + desc.setValid(((Boolean)newvalue).booleanValue()); + } + } + } + } + ); + desc.setValid(panel.getSelectedDatasource() != null); + panel.setSize(panel.getPreferredSize()); + dlg.pack(); + dlg.setVisible(true); + } finally { + if (dlg != null) { + getDlg().dispose(); + } + } + return desc.getValue() == DialogDescriptor.CLOSED_OPTION + ? panel.getSelectedDatasource() + : null; + + } + + /** Returns the selected datasource or null if no datasource was selected. + * + * @return datasource or null if no datasource was selected + */ + public String getSelectedDatasource() { + if ((datasourceList.getSelectedIndex() == -1) || (datasourceList.getFirstVisibleIndex() == -1)) { + return null; + } else { + return ((Datasource)datasourceList.getSelectedValue()).getJndiName(); + } + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + jScrollPane2 = new javax.swing.JScrollPane(); + datasourceList = new javax.swing.JList(); + jTextArea1 = new javax.swing.JTextArea(); + jTextArea2 = new javax.swing.JTextArea(); + jButtonAddConnection = new javax.swing.JButton(); + + setLayout(new java.awt.GridBagLayout()); + + jScrollPane2.setMinimumSize(new java.awt.Dimension(200, 100)); + + datasourceList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + datasourceList.setPreferredSize(null); + datasourceList.setVerifyInputWhenFocusTarget(false); + datasourceList.setVisibleRowCount(4); + jScrollPane2.setViewportView(datasourceList); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(6, 12, 12, 12); + add(jScrollPane2, gridBagConstraints); + + jTextArea1.setColumns(25); + jTextArea1.setEditable(false); + jTextArea1.setLineWrap(true); + jTextArea1.setText(NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "LBL_SelectDatasource")); // NOI18N + jTextArea1.setWrapStyleWord(true); + jTextArea1.setFocusable(false); + jTextArea1.setOpaque(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(12, 12, 6, 12); + add(jTextArea1, gridBagConstraints); + jTextArea1.getAccessibleContext().setAccessibleName("Resolve Datasource"); + + jTextArea2.setEditable(false); + jTextArea2.setLineWrap(true); + jTextArea2.setText(org.openide.util.NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "LBL_MissingDatabaseConnectionWarning")); // NOI18N + jTextArea2.setWrapStyleWord(true); + jTextArea2.setFocusable(false); + jTextArea2.setOpaque(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(12, 12, 6, 12); + add(jTextArea2, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(jButtonAddConnection, org.openide.util.NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "LBL_AddDatabaseConnection")); // NOI18N + jButtonAddConnection.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButtonAddConnectionActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.anchor = java.awt.GridBagConstraints.LAST_LINE_START; + gridBagConstraints.insets = new java.awt.Insets(0, 12, 5, 0); + add(jButtonAddConnection, gridBagConstraints); + jButtonAddConnection.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "ACSN_AddDatabaseConnection")); // NOI18N + jButtonAddConnection.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "ACSD_AddDatabaseConnection")); // NOI18N + }// //GEN-END:initComponents + + private void jButtonAddConnectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddConnectionActionPerformed + Datasource brokenDatasource = (Datasource)datasourceList.getSelectedValue(); + addDatabaseConnection(brokenDatasource); + + if (datasourceList.getModel().getSize() > 0) { + // if (datasourceList.getModel().getSize() > 0 && !datasourceList.isVisible()) { + // datasourceList.setVisible(true); + jScrollPane2.setBorder(scrollPaneBorder); + jTextArea2.setText(org.openide.util.NbBundle.getMessage(MissingDatabaseConnectionWarning.class, "LBL_SelectDatasource")); + } + + initDatasourceList(); +}//GEN-LAST:event_jButtonAddConnectionActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JList datasourceList; + private javax.swing.JButton jButtonAddConnection; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextArea jTextArea2; + // End of variables declaration//GEN-END:variables + + + private final class DatasourceListModel extends AbstractListModel implements Runnable, ConnectionListener { + private final RequestProcessor BROKEN_DATASOURCE_RP = new RequestProcessor("WebLogicalViewProvider.BROKEN_DATASOURCE_RP"); //NOI18N + private Set datasources; + + public DatasourceListModel() { + datasources = BrokenDatasourceSupport.getBrokenDatasources(project); + addConnectionListener(); + } + + public synchronized int getSize() { + return datasources.size(); + } + + /* + * + * Return the datasource corresponding to the selected position in datasourceList + */ + public synchronized Object getElementAt(int index) { + Iterator it = datasources.iterator(); + int i = 0; + while (it.hasNext()) { + if (index >= 0 && index <= datasources.size()) { + if (i == index) { + return it.next(); + } + + // get the next datasource from the set of datasources + it.next(); + i++; + } + } + + return null; + } + + /* + * Refresh model to be done in RP thread for checking database connections + * checking connections might be done by another thread at the same time. + */ + public synchronized void refreshModel() { + // Checking for valid database connections for each datasource + // may take awhile, so run in a separate thread + if (task == null) { + task = BROKEN_DATASOURCE_RP.create(this); + } + task.schedule(100); + } + + public void run() { + datasources = BrokenDatasourceSupport.getBrokenDatasources(project); + if (datasources.isEmpty()) { + removeConnectionListener(); + getDlg().dispose(); + } + } + + // Listen for any connections changed in DB Explorer and refresh model accordingly + public void connectionsChanged() { + refreshModel(); + } + + private void addConnectionListener() { + ConnectionManager.getDefault().addConnectionListener(this); + } + + private void removeConnectionListener() { + ConnectionManager.getDefault().removeConnectionListener(this); + } + } + + private static final class DatasourceRenderer extends JLabel implements ListCellRenderer { + + DatasourceRenderer() { + setOpaque(true); + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value instanceof Datasource) { + String jndiName = ((Datasource)value).getJndiName(); + setText(jndiName.substring(jndiName.indexOf("/")+1)); + } + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + return this; + } + } + + /** + * Post the Add Database Connection dialog passing the data source information for populating the dialgo + * @param brokenDatasource data source that requires a registered database connection + */ + private static void addDatabaseConnection(Datasource brokenDatasource) { + // next check to see if the driver has been added + String driverName = brokenDatasource.getDriverClassName(); + final JDBCDriver matchingDriver = findMatchingDriver(driverName); + final Datasource edtDS = brokenDatasource; + + // if matchingDriver is null, user can add driver in the Add Connection dialog + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ConnectionManager.getDefault().showAddConnectionDialogFromEventThread(matchingDriver, edtDS.getUrl(), edtDS.getUsername(), edtDS.getPassword()); + } + }); + } + + /* + * Find a matching driver registered with the IDE + * public: to-be-used outside this class + */ + private static JDBCDriver findMatchingDriver(String driverClass) { + int i = 0; + JDBCDriver[] newDrivers; + newDrivers = JDBCDriverManager.getDefault().getDrivers(); + + for (i = 0; i