001: /*
002: * DriversPanel.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.executequery.gui.drivers;
023:
024: import java.awt.Dimension;
025: import java.awt.GridBagConstraints;
026: import java.awt.GridBagLayout;
027: import java.awt.Insets;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.FocusEvent;
030: import java.awt.event.FocusListener;
031: import java.awt.event.ItemEvent;
032: import java.awt.event.ItemListener;
033: import java.awt.print.Printable;
034: import java.io.File;
035: import java.io.IOException;
036: import java.net.MalformedURLException;
037: import java.util.List;
038: import java.util.Vector;
039: import javax.swing.JButton;
040: import javax.swing.JComboBox;
041: import javax.swing.JFileChooser;
042: import javax.swing.JLabel;
043: import javax.swing.JOptionPane;
044: import javax.swing.JPanel;
045: import javax.swing.JTextField;
046: import org.executequery.DatabaseDefinitionCache;
047: import org.executequery.GUIUtilities;
048: import org.executequery.JDBCProperties;
049: import org.executequery.ValidationException;
050: import org.underworldlabs.swing.DynamicComboBoxModel;
051: import org.underworldlabs.swing.actions.ActionUtilities;
052: import org.underworldlabs.swing.actions.ReflectiveAction;
053: import org.executequery.base.TabView;
054: import org.executequery.databasemediators.DatabaseDriver;
055: import org.executequery.gui.forms.AbstractFormObjectViewPanel;
056: import org.executequery.components.FileChooserDialog;
057: import org.executequery.components.TextFieldPanel;
058: import org.executequery.datasource.DatabaseDefinition;
059: import org.underworldlabs.swing.FileSelector;
060: import org.underworldlabs.util.MiscUtils;
061: import org.executequery.gui.*;
062:
063: /* ----------------------------------------------------------
064: * CVS NOTE: Changes to the CVS repository prior to the
065: * release of version 3.0.0beta1 has meant a
066: * resetting of CVS revision numbers.
067: * ----------------------------------------------------------
068: */
069:
070: /**
071: *
072: * @author Takis Diakoumis
073: * @version $Revision: 1.12 $
074: * @date $Date: 2006/09/26 13:17:03 $
075: */
076: public class DriversPanel extends AbstractFormObjectViewPanel implements
077: TabView, FocusListener, ItemListener {
078:
079: public static final String TITLE = "Drivers";
080: public static final String FRAME_ICON = "DatabaseDrivers16.gif";
081:
082: private JTextField nameField;
083: private JTextField descField;
084: private JTextField pathField;
085: private JTextField classField;
086:
087: private JComboBox driverUrlCombo;
088: private JComboBox databaseNameCombo;
089:
090: private DynamicComboBoxModel urlComboModel;
091:
092: /** the currently selected driver */
093: private DatabaseDriver databaseDriver;
094:
095: /** the parent panel containing the selection tree */
096: private DriverViewPanel parent;
097:
098: /** Creates a new instance of DriversPanel */
099: public DriversPanel(DriverViewPanel parent) {
100: super ();
101: this .parent = parent;
102: init();
103: }
104:
105: private void init() {
106:
107: ReflectiveAction action = new ReflectiveAction(this );
108:
109: JButton browseButton = ActionUtilities.createButton(action,
110: "Browse", "browseDrivers");
111: JButton findButton = ActionUtilities.createButton(action,
112: "Find", "findDriverClass");
113:
114: Dimension btnDim = new Dimension(70, 23);
115: browseButton.setPreferredSize(btnDim);
116: findButton.setPreferredSize(btnDim);
117: browseButton.setMinimumSize(btnDim);
118: findButton.setMinimumSize(btnDim);
119:
120: Insets btnMargin = new Insets(0, 0, 0, 0);
121: browseButton.setMargin(btnMargin);
122: findButton.setMargin(btnMargin);
123:
124: nameField = new JTextField();
125: descField = new JTextField();
126: pathField = new JTextField();
127: classField = new JTextField();
128:
129: nameField.addFocusListener(this );
130:
131: // retrieve the db name list
132: List<DatabaseDefinition> databases = DatabaseDefinitionCache
133: .getDatabaseDefinitions();
134: int count = databases.size() + 1;
135: Vector<DatabaseDefinition> _databases = new Vector(count);
136:
137: // create a new list with a dummy value
138: for (int i = 1; i < count; i++) {
139: _databases.add(databases.get(i - 1));
140: }
141: // add the dummy
142: _databases.insertElementAt(new DatabaseDefinition(
143: DatabaseDefinitionCache.INVALID_DATABASE_ID,
144: "Select..."), 0);
145: databaseNameCombo = new JComboBox(_databases);
146: databaseNameCombo.addItemListener(this );
147:
148: urlComboModel = new DynamicComboBoxModel();
149: driverUrlCombo = new JComboBox(urlComboModel);
150: driverUrlCombo.setEditable(true);
151:
152: JPanel base = new TextFieldPanel(new GridBagLayout());
153: GridBagConstraints gbc = new GridBagConstraints();
154: gbc.gridy++;
155: gbc.insets = new Insets(10, 10, 5, 0);
156: gbc.anchor = GridBagConstraints.NORTHWEST;
157: base.add(new JLabel("Driver Name:"), gbc);
158: gbc.gridy++;
159: gbc.insets.top = 0;
160: base.add(new JLabel("Description:"), gbc);
161: gbc.gridy++;
162: base.add(new JLabel("Database:"), gbc);
163: gbc.gridy++;
164: base.add(new JLabel("JDBC URL:"), gbc);
165: gbc.gridy++;
166: base.add(new JLabel("Path:"), gbc);
167: gbc.gridy++;
168: base.add(new JLabel("Class Name:"), gbc);
169: gbc.gridy = 0;
170: gbc.gridx = 1;
171: gbc.insets.right = 10;
172: gbc.insets.top = 10;
173: gbc.weightx = 1.0;
174: gbc.fill = GridBagConstraints.HORIZONTAL;
175: gbc.gridwidth = GridBagConstraints.REMAINDER;
176: base.add(nameField, gbc);
177: gbc.gridy++;
178: gbc.insets.top = 0;
179: base.add(descField, gbc);
180: gbc.gridy++;
181: base.add(databaseNameCombo, gbc);
182: gbc.gridy++;
183: base.add(driverUrlCombo, gbc);
184: gbc.gridy++;
185: gbc.gridwidth = 1;
186: gbc.insets.right = 0;
187: base.add(pathField, gbc);
188: gbc.gridx = 2;
189: gbc.weightx = 0;
190: gbc.insets.right = 10;
191: gbc.fill = GridBagConstraints.NONE;
192: base.add(browseButton, gbc);
193: gbc.gridy++;
194: gbc.gridx = 1;
195: gbc.weightx = 1.0;
196: gbc.insets.right = 0;
197: gbc.fill = GridBagConstraints.HORIZONTAL;
198: base.add(classField, gbc);
199: gbc.gridx = 2;
200: gbc.weightx = 0;
201: gbc.weighty = 1.0;
202: gbc.insets.right = 10;
203: gbc.fill = GridBagConstraints.NONE;
204: base.add(findButton, gbc);
205:
206: setHeaderText("Database Driver");
207: setHeaderIcon(GUIUtilities.loadIcon("DatabaseDriver24.gif"));
208: setContentPanel(base);
209: }
210:
211: public void itemStateChanged(ItemEvent e) {
212: // interested in selections only
213: if (e.getStateChange() == ItemEvent.DESELECTED) {
214: return;
215: }
216:
217: DatabaseDefinition database = getSelectedDatabase();
218: int id = database.getId();
219: if (id > 0) {
220: // reload the urls for the combo selection
221: resetUrlCombo(database);
222: } else {
223: // otherwise clear all
224: urlComboModel.removeAllElements();
225: }
226: }
227:
228: public DatabaseDefinition getSelectedDatabase() {
229: return (DatabaseDefinition) databaseNameCombo.getSelectedItem();
230: }
231:
232: /**
233: * Saves the driver data to file.
234: */
235: protected boolean saveDrivers() {
236: //Log.debug("saving drivers");
237: try {
238: int saved = JDBCProperties.saveDrivers();
239: } catch (ValidationException e) {
240: GUIUtilities.displayErrorMessage(e.getMessage());
241: return false;
242: }
243: return true;
244: }
245:
246: protected void enableFields(boolean enable) {
247: nameField.setEnabled(enable);
248: descField.setEnabled(enable);
249: pathField.setEnabled(enable);
250: classField.setEnabled(enable);
251: driverUrlCombo.setEnabled(enable);
252: databaseNameCombo.setEnabled(enable);
253: }
254:
255: /**
256: * Saves the driver info and mods the tree node value
257: * when the name field loses focus.
258: */
259: public void focusLost(FocusEvent e) {
260: if (panelSelected) {
261: populateAndSave();
262: }
263: }
264:
265: public void focusGained(FocusEvent e) {
266: }
267:
268: private boolean populateAndSave() {
269: populateDriverObject();
270: return saveDrivers();
271: }
272:
273: // --------------------------------------------
274: // DockedTabView implementation
275: // --------------------------------------------
276:
277: private boolean panelSelected = true;
278:
279: /**
280: * Indicates the panel is being removed from the pane
281: */
282: public boolean tabViewClosing() {
283: panelSelected = false;
284: //nameField.removeFocusListener(this);
285: return populateAndSave();
286: }
287:
288: /**
289: * Indicates the panel is being selected in the pane
290: */
291: public boolean tabViewSelected() {
292: panelSelected = true;
293: return true;
294: }
295:
296: /**
297: * Indicates the panel is being selected in the pane
298: */
299: public boolean tabViewDeselected() {
300: return tabViewClosing();
301: }
302:
303: // --------------------------------------------
304:
305: public void findDriverClass(ActionEvent e) {
306: if (databaseDriver.getId() == JDBCProperties.DEFAULT_ODBC_ID) {
307: return;
308: }
309:
310: String paths = pathField.getText();
311:
312: if (MiscUtils.isNull(paths)) {
313: GUIUtilities
314: .displayErrorMessage("A valid path to the JDBC library is required");
315: return;
316: }
317:
318: String[] drivers = null;
319: try {
320: GUIUtilities.showWaitCursor();
321: drivers = MiscUtils.findImplementingClasses(
322: "java.sql.Driver", paths);
323: } catch (MalformedURLException urlExc) {
324: GUIUtilities
325: .displayErrorMessage("A valid path to the JDBC library is required");
326: } catch (IOException ioExc) {
327: GUIUtilities
328: .displayErrorMessage("An error occured accessing the specified file:\n"
329: + ioExc.getMessage());
330: } finally {
331: GUIUtilities.showNormalCursor();
332: }
333:
334: if (drivers == null || drivers.length == 0) {
335: GUIUtilities
336: .displayWarningMessage("No valid classes implementing java.sql.Driver\n"
337: + "were found in the specified resource");
338: return;
339: }
340:
341: int result = -1;
342: String value = null;
343: while (true) {
344: SimpleValueSelectionDialog dialog = new SimpleValueSelectionDialog(
345: "Select JDBC Driver", drivers);
346: result = dialog.showDialog();
347:
348: if (result == JOptionPane.OK_OPTION) {
349: value = dialog.getValue();
350:
351: if (value == null) {
352: GUIUtilities
353: .displayErrorMessage("You must select a driver from the list");
354: } else {
355: classField.setText(value);
356: databaseDriver.setClassName(value);
357: break;
358: }
359:
360: } else {
361: break;
362: }
363:
364: }
365: }
366:
367: public void browseDrivers(ActionEvent e) {
368: if (databaseDriver.getId() == JDBCProperties.DEFAULT_ODBC_ID) {
369: return;
370: }
371:
372: FileSelector jarFiles = new FileSelector(
373: new String[] { "jar" }, "Java Archive files");
374: FileSelector zipFiles = new FileSelector(
375: new String[] { "zip" }, "ZIP Archive files");
376:
377: FileChooserDialog fileChooser = new FileChooserDialog();
378: fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
379: fileChooser.addChoosableFileFilter(zipFiles);
380: fileChooser.addChoosableFileFilter(jarFiles);
381:
382: fileChooser.setDialogTitle("Select JDBC Drivers...");
383: fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
384:
385: fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
386: fileChooser.setMultiSelectionEnabled(true);
387:
388: int result = fileChooser.showDialog(GUIUtilities
389: .getParentFrame(), "Select");
390:
391: if (result == JFileChooser.CANCEL_OPTION) {
392: return;
393: }
394:
395: File[] files = fileChooser.getSelectedFiles();
396:
397: char COLON = ';';
398: StringBuffer sb = new StringBuffer(100);
399:
400: for (int i = 0; i < files.length; i++) {
401: sb.append(files[i].getAbsolutePath());
402: if (i != files.length - 1) {
403: sb.append(COLON);
404: }
405: }
406:
407: pathField.setText(sb.toString());
408: databaseDriver.setPath(pathField.getText());
409: }
410:
411: /**
412: * Checks the current selection for a name change
413: * to be propagated back to the tree view.
414: */
415: private void checkNameUpdate() {
416: String oldName = databaseDriver.getName();
417: String newName = nameField.getText().trim();
418: if (!oldName.equals(newName)) {
419: databaseDriver.setName(newName);
420: parent.nodeNameValueChanged(databaseDriver);
421: }
422: }
423:
424: /**
425: * Populates the driver object from the field values.
426: */
427: private void populateDriverObject() {
428: // ODBC driver can not be changed
429: if (databaseDriver.getId() == JDBCProperties.DEFAULT_ODBC_ID) {
430: return;
431: }
432:
433: databaseDriver.setDescription(descField.getText());
434: databaseDriver.setClassName(classField.getText());
435: databaseDriver.setURL(driverUrlCombo.getEditor().getItem()
436: .toString());
437: databaseDriver.setPath(pathField.getText());
438:
439: DatabaseDefinition database = getSelectedDatabase();
440: if (database.getId() > 0) {
441: databaseDriver.setDatabaseType(database.getId());
442: }
443:
444: checkNameUpdate();
445:
446: if (databaseDriver.getId() == 0) {
447: databaseDriver.setId(System.currentTimeMillis());
448: // need to check exisitng conns with this driver's name
449: }
450:
451: }
452:
453: public void setDriver(DatabaseDriver databaseDriver) {
454: // store the field values of the current selection
455: if (this .databaseDriver != null) {
456: populateDriverObject();
457: }
458:
459: try {
460: databaseNameCombo.removeItemListener(this );
461: this .databaseDriver = databaseDriver;
462: nameField.setText(databaseDriver.getName());
463: descField.setText(databaseDriver.getDescription().equals(
464: "Not Available") ? "" : databaseDriver
465: .getDescription());
466: classField.setText(databaseDriver.getClassName());
467: pathField.setText(databaseDriver.getPath());
468:
469: int databaseId = databaseDriver.getType();
470: DatabaseDefinition database = DatabaseDefinitionCache
471: .getDatabaseDefinition(databaseId);
472:
473: if (database != null) {
474: resetUrlCombo(database);
475: databaseNameCombo.setSelectedItem(database);
476: } else {
477: urlComboModel.removeAllElements();
478: databaseNameCombo.setSelectedIndex(0);
479: }
480:
481: String url = databaseDriver.getURL();
482: if (!MiscUtils.isNull(url)) {
483: urlComboModel.insertElementAt(url, 0);
484: }
485:
486: if (urlComboModel.getSize() > 0) {
487: driverUrlCombo.setSelectedIndex(0);
488: }
489:
490: nameField.requestFocusInWindow();
491: nameField.selectAll();
492: } finally {
493: databaseNameCombo.addItemListener(this );
494: }
495: }
496:
497: private void resetUrlCombo(DatabaseDefinition database) {
498: urlComboModel.removeAllElements();
499: for (int i = 0; i < database.getUrlCount(); i++) {
500: urlComboModel.addElement(database.getUrl(i));
501: }
502: }
503:
504: public DatabaseDriver getDriver() {
505: return databaseDriver;
506: }
507:
508: /** Performs some cleanup and releases resources before being closed. */
509: public void cleanup() {
510:
511: }
512:
513: /** Refreshes the data and clears the cache */
514: public void refresh() {
515: }
516:
517: /** Returns the print object - if any */
518: public Printable getPrintable() {
519: return null;
520: }
521:
522: /** Returns the name of this panel */
523: public String getLayoutName() {
524: return TITLE;
525: }
526:
527: }
|