1 /*
   2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 
  42 import java.sql.Connection;
  43 import java.sql.DriverManager;
  44 import java.sql.ResultSet;
  45 import java.sql.ResultSetMetaData;
  46 import java.sql.SQLException;
  47 import java.sql.Statement;
  48 import java.sql.Types;
  49 import java.util.ArrayList;
  50 import java.util.List;
  51 import javax.swing.table.AbstractTableModel;
  52 
  53 
  54 /**
  55  * An adaptor, transforming the JDBC interface to the TableModel interface.
  56  *
  57  * @author Philip Milne
  58  */
  59 @SuppressWarnings("serial")
  60 public class JDBCAdapter extends AbstractTableModel {
  61 
  62     Connection connection;
  63     Statement statement;
  64     ResultSet resultSet;
  65     String[] columnNames = {};
  66     List<List<Object>> rows = new ArrayList<List<Object>>();
  67     ResultSetMetaData metaData;
  68 
  69     public JDBCAdapter(String url, String driverName,
  70             String user, String passwd) {
  71         try {
  72             Class.forName(driverName);
  73             System.out.println("Opening db connection");
  74 
  75             connection = DriverManager.getConnection(url, user, passwd);
  76             statement = connection.createStatement();
  77         } catch (ClassNotFoundException ex) {
  78             System.err.println("Cannot find the database driver classes.");
  79             System.err.println(ex);
  80         } catch (SQLException ex) {
  81             System.err.println("Cannot connect to this database.");
  82             System.err.println(ex);
  83         }
  84     }
  85 
  86     public void executeQuery(String query) {
  87         if (connection == null || statement == null) {
  88             System.err.println("There is no database to execute the query.");
  89             return;
  90         }
  91         try {
  92             resultSet = statement.executeQuery(query);
  93             metaData = resultSet.getMetaData();
  94 
  95             int numberOfColumns = metaData.getColumnCount();
  96             columnNames = new String[numberOfColumns];
  97             // Get the column names and cache them.
  98             // Then we can close the connection.
  99             for (int column = 0; column < numberOfColumns; column++) {
 100                 columnNames[column] = metaData.getColumnLabel(column + 1);
 101             }
 102 
 103             // Get all rows.
 104             rows = new ArrayList<List<Object>>();
 105             while (resultSet.next()) {
 106                 List<Object> newRow = new ArrayList<Object>();
 107                 for (int i = 1; i <= getColumnCount(); i++) {
 108                     newRow.add(resultSet.getObject(i));
 109                 }
 110                 rows.add(newRow);
 111             }
 112             //  close(); Need to copy the metaData, bug in jdbc:odbc driver.
 113 
 114             // Tell the listeners a new table has arrived.
 115             fireTableChanged(null);
 116         } catch (SQLException ex) {
 117             System.err.println(ex);
 118         }
 119     }
 120 
 121     public void close() throws SQLException {
 122         System.out.println("Closing db connection");
 123         resultSet.close();
 124         statement.close();
 125         connection.close();
 126     }
 127 
 128     @Override
 129     protected void finalize() throws Throwable {
 130         close();
 131         super.finalize();
 132     }
 133 
 134     //////////////////////////////////////////////////////////////////////////
 135     //
 136     //             Implementation of the TableModel Interface
 137     //
 138     //////////////////////////////////////////////////////////////////////////
 139     // MetaData
 140     @Override
 141     public String getColumnName(int column) {
 142         if (columnNames[column] != null) {
 143             return columnNames[column];
 144         } else {
 145             return "";
 146         }
 147     }
 148 
 149     @Override
 150     public Class<?> getColumnClass(int column) {
 151         int type;
 152         try {
 153             type = metaData.getColumnType(column + 1);
 154         } catch (SQLException e) {
 155             return super.getColumnClass(column);
 156         }
 157 
 158         switch (type) {
 159             case Types.CHAR:
 160             case Types.VARCHAR:
 161             case Types.LONGVARCHAR:
 162                 return String.class;
 163 
 164             case Types.BIT:
 165                 return Boolean.class;
 166 
 167             case Types.TINYINT:
 168             case Types.SMALLINT:
 169             case Types.INTEGER:
 170                 return Integer.class;
 171 
 172             case Types.BIGINT:
 173                 return Long.class;
 174 
 175             case Types.FLOAT:
 176             case Types.DOUBLE:
 177                 return Double.class;
 178 
 179             case Types.DATE:
 180                 return java.sql.Date.class;
 181 
 182             default:
 183                 return Object.class;
 184         }
 185     }
 186 
 187     @Override
 188     public boolean isCellEditable(int row, int column) {
 189         try {
 190             return metaData.isWritable(column + 1);
 191         } catch (SQLException e) {
 192             return false;
 193         }
 194     }
 195 
 196     public int getColumnCount() {
 197         return columnNames.length;
 198     }
 199 
 200     // Data methods
 201     public int getRowCount() {
 202         return rows.size();
 203     }
 204 
 205     public Object getValueAt(int aRow, int aColumn) {
 206         List<Object> row = rows.get(aRow);
 207         return row.get(aColumn);
 208     }
 209 
 210     public String dbRepresentation(int column, Object value) {
 211         int type;
 212 
 213         if (value == null) {
 214             return "null";
 215         }
 216 
 217         try {
 218             type = metaData.getColumnType(column + 1);
 219         } catch (SQLException e) {
 220             return value.toString();
 221         }
 222 
 223         switch (type) {
 224             case Types.INTEGER:
 225             case Types.DOUBLE:
 226             case Types.FLOAT:
 227                 return value.toString();
 228             case Types.BIT:
 229                 return ((Boolean) value).booleanValue() ? "1" : "0";
 230             case Types.DATE:
 231                 return value.toString(); // This will need some conversion.
 232             default:
 233                 return "\"" + value.toString() + "\"";
 234         }
 235 
 236     }
 237 
 238     @Override
 239     public void setValueAt(Object value, int row, int column) {
 240         try {
 241             String tableName = metaData.getTableName(column + 1);
 242             // Some of the drivers seem buggy, tableName should not be null.
 243             if (tableName == null) {
 244                 System.out.println("Table name returned null.");
 245             }
 246             String columnName = getColumnName(column);
 247             String query =
 248                     "update " + tableName + " set " + columnName + " = "
 249                     + dbRepresentation(column, value) + " where ";
 250             // We don't have a model of the schema so we don't know the
 251             // primary keys or which columns to lock on. To demonstrate
 252             // that editing is possible, we'll just lock on everything.
 253             for (int col = 0; col < getColumnCount(); col++) {
 254                 String colName = getColumnName(col);
 255                 if (colName.equals("")) {
 256                     continue;
 257                 }
 258                 if (col != 0) {
 259                     query = query + " and ";
 260                 }
 261                 query = query + colName + " = " + dbRepresentation(col,
 262                         getValueAt(row, col));
 263             }
 264             System.out.println(query);
 265             System.out.println("Not sending update to database");
 266             // statement.executeQuery(query);
 267         } catch (SQLException e) {
 268             //     e.printStackTrace();
 269             System.err.println("Update failed");
 270         }
 271         List<Object> dataRow = rows.get(row);
 272         dataRow.set(column, value);
 273 
 274     }
 275 }