|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.mdr.persistence.jdbcimpl; import org.netbeans.mdr.persistence.*; import org.netbeans.mdr.util.*; import java.sql.*; import java.util.*; import java.io.*; /** * JdbcStorage implements the MDR Storage interface using JDBC. * * @author John V. Sichi * @version $Id: JdbcStorage.java,v 1.6 2004/03/05 00:33:57 jsichi Exp $ */ class JdbcStorage implements Storage { public static final String MOFID_SEQ_TABLE_NAME = "MOFID_SEQ"; public static final String MOFID_SEQ_COL_NAME = "MOFID_SEQ_NEXT"; public static final String KEY_COL_PREFIX = "IDX_KEY"; public static final String SINGLE_VAL_COL_PREFIX = "IDX_SVAL"; public static final String MULTI_VAL_COL_PREFIX = "IDX_MVAL"; public static final String ORDINAL_COL_NAME = "IDX_ORD"; public static final String SURROGATE_COL_NAME = "IDX_SUR"; public static final String PRIMARY_INDEX_NAME = "PRIMARY_INDEX"; private final Connection jdbcConnection; private final DatabaseMetaData dbMetaData; private final String idQuote; private final String schemaName; private final String userName; private final String storageId; private final boolean realSchema; private final Map entryTypeToDataTypeMap; private Statement jdbcStmt; private ResultSet jdbcResultSet; private long nextSerialNumber; private Map nameToIndexMap; private LazyPreparedStatement sqlUpdateSerialNumber; // REVIEW: if this gets too bloated for a big model, may need to turn this // into a cache instead of a map private Map sqlToPreparedStatementMap; private JdbcPrimaryIndex primaryIndex; JdbcStorage( Properties properties, String storageId) throws StorageException { this.storageId = storageId; schemaName = properties.getProperty( JdbcStorageFactory.STORAGE_SCHEMA_NAME); userName = properties.getProperty( JdbcStorageFactory.STORAGE_USER_NAME); entryTypeToDataTypeMap = new HashMap(); createTypeMap(properties); String url = properties.getProperty( JdbcStorageFactory.STORAGE_URL); String password = properties.getProperty( JdbcStorageFactory.STORAGE_PASSWORD); boolean success = false; try { // REVIEW: maybe connect/disconnect should correspond to // open/close instead of constructor/shutdown? jdbcConnection = DriverManager.getConnection(url,userName,password); jdbcConnection.setAutoCommit(false); jdbcStmt = jdbcConnection.createStatement(); dbMetaData = jdbcConnection.getMetaData(); realSchema = dbMetaData.supportsSchemasInTableDefinitions(); idQuote = dbMetaData.getIdentifierQuoteString(); success = true; } catch (SQLException ex) { throw new JdbcStorageException(ex); } finally { if (!success) { rollbackConnection(); closeConnection(); } } } private void createTypeMap(Properties properties) { entryTypeToDataTypeMap.put( EntryType.MOFID, properties.getProperty( JdbcStorageFactory.STORAGE_DATATYPE_MOFID, "BIGINT")); entryTypeToDataTypeMap.put( EntryType.STREAMABLE, properties.getProperty( JdbcStorageFactory.STORAGE_DATATYPE_STREAMABLE, "LONGVARBINARY")); entryTypeToDataTypeMap.put( EntryType.STRING, properties.getProperty( JdbcStorageFactory.STORAGE_DATATYPE_STRING, "VARCHAR(2000)")); entryTypeToDataTypeMap.put( EntryType.INT, properties.getProperty( JdbcStorageFactory.STORAGE_DATATYPE_INT, "BIGINT")); } // implement Storage public String getName() { return schemaName + ".jdbc"; } // implement Storage public String getStorageId () { return storageId; } private void writeSerialNumber(long serialNumber) throws StorageException { executeUpdate( sqlUpdateSerialNumber, new Object[]{new Long(serialNumber)}); } // implement Storage public synchronized long getSerialNumber() { return nextSerialNumber++; } // implement Storage public MOFID readMOFID (java.io.InputStream inputStream) throws StorageException { // NOTE: ripped from memoryimpl try { String storageId = IOUtils.readString(inputStream); if (storageId == null) { storageId = this.storageId; } long serial = IOUtils.readLong(inputStream); return new MOFID(serial, storageId); } catch (java.io.IOException ioException) { throw new StorageIOException(ioException); } } // implement Storage public void writeMOFID (java.io.OutputStream outputStream, MOFID mofid) throws StorageException { // NOTE: ripped from memoryimpl try { if (storageId.equals(mofid.getStorageID())) { IOUtils.writeString(outputStream, null); } else { IOUtils.writeString(outputStream, mofid.getStorageID()); } IOUtils.writeLong(outputStream, mofid.getSerialNumber()); } catch (IOException ioException) { throw new StorageIOException(ioException); } } DatabaseMetaData getDatabaseMetaData() { return dbMetaData; } private String getQualifiedTableName(String tableName) { if (realSchema) { return idQuote + schemaName + idQuote + "." + idQuote + tableName + idQuote; } else { return idQuote + schemaName + "_" + tableName + idQuote; } } private String getQualifiedSchemaName() { return idQuote + schemaName + idQuote; } private void rollbackConnection() { closeResultSet(); if (jdbcConnection != null) { try { jdbcConnection.rollback(); } catch (SQLException ex) { // TODO: trace } } } private long readSerialNumber() { try { jdbcResultSet = jdbcStmt.executeQuery( "select * from "+getQualifiedTableName(MOFID_SEQ_TABLE_NAME)); jdbcResultSet.next(); long x = jdbcResultSet.getLong(1); return x; } catch (SQLException ex) { return -1; } } // implement Storage public synchronized boolean exists() throws StorageException { long x = readSerialNumber(); return x != -1; } // implement Storage public synchronized boolean delete() throws StorageException { rollbackConnection(); try { if (realSchema) { jdbcResultSet = dbMetaData.getSchemas(); boolean found = false; while (jdbcResultSet.next()) { String name = jdbcResultSet.getString(1); if (name.equals(schemaName)) { found = true; break; } } closeResultSet(); if (!found) { // schema doesn't even exist return true; } jdbcStmt.execute( "drop schema " + getQualifiedSchemaName() + " cascade"); } else { jdbcResultSet = dbMetaData.getTables( null,null,schemaName + "%",null); List tables = new ArrayList(); while (jdbcResultSet.next()) { tables.add(jdbcResultSet.getString("TABLE_NAME")); } closeResultSet(); Iterator iter = tables.iterator(); while (iter.hasNext()) { String tableName = (String) iter.next(); jdbcStmt.execute( "drop table " + idQuote + tableName + idQuote); } } jdbcConnection.commit(); return true; } catch (SQLException ex) { rollbackConnection(); return false; } } private boolean isBlank(String s) { return (s == null) || (s.length() == 0); } // implement Storage public synchronized void create(boolean replace, ObjectResolver resolver) throws StorageException { try { if (replace) { delete(); } rollbackConnection(); if (realSchema) { String sql = "create schema " + getQualifiedSchemaName(); if (!isBlank(userName)) { sql = sql + " authorization " + userName; } jdbcStmt.execute(sql); } String intType = getDataType(EntryType.INT); jdbcStmt.execute( "create table " + getQualifiedTableName(MOFID_SEQ_TABLE_NAME) + "(" + MOFID_SEQ_COL_NAME + " " + intType + " not null primary key)"); jdbcStmt.executeUpdate( "insert into " + getQualifiedTableName(MOFID_SEQ_TABLE_NAME) + " values(1)"); nextSerialNumber = 1; openImpl(); createSinglevaluedIndex( PRIMARY_INDEX_NAME, EntryType.MOFID, EntryType.STREAMABLE); loadPrimaryIndex(); jdbcConnection.commit(); } catch (SQLException ex) { rollbackConnection(); throw new JdbcStorageException(ex); } } // implement Storage public synchronized void open( boolean createOnNoExist, ObjectResolver resolver) throws StorageException { nextSerialNumber = readSerialNumber(); if (nextSerialNumber == -1) { if (createOnNoExist) { create(false,resolver); return; } else { throw new StorageBadRequestException( "Storage " + getName() + " does not exist."); } } try { openImpl(); loadPrimaryIndex(); } catch (SQLException ex) { throw new JdbcStorageException(ex); } } private void openImpl() throws SQLException { nameToIndexMap = new HashMap(); sqlToPreparedStatementMap = new HashMap(); sqlUpdateSerialNumber = new LazyPreparedStatement( "update " + getQualifiedTableName(MOFID_SEQ_TABLE_NAME) + " set " + MOFID_SEQ_COL_NAME + " = ?"); } private void loadPrimaryIndex() throws StorageException { primaryIndex = (JdbcPrimaryIndex) getIndex(PRIMARY_INDEX_NAME); } // implement Storage public synchronized void close() throws StorageException { nameToIndexMap = null; sqlUpdateSerialNumber = null; if (sqlToPreparedStatementMap != null) { Iterator iter = sqlToPreparedStatementMap.values().iterator(); while (iter.hasNext()) { PreparedStatement ps = (PreparedStatement) iter.next(); closePreparedStatement(ps); } sqlToPreparedStatementMap = null; } rollbackConnection(); } private void closePreparedStatement(PreparedStatement ps) { if (ps == null) { return; } try { ps.close(); } catch (SQLException ex) { // TODO: trace } } private void closeStatement() { if (jdbcStmt == null) { return; } try { jdbcStmt.close(); } catch (SQLException ex) { // TODO: trace } finally { jdbcStmt = null; } } private void closeResultSet() { if (jdbcResultSet == null) { return; } try { jdbcResultSet.close(); } catch (SQLException ex) { // TODO: trace } finally { jdbcResultSet = null; } } private void closeConnection() { if (jdbcConnection == null) { return; } try { jdbcConnection.close(); } catch (SQLException ex) { // TODO: trace } } // implement Storage public synchronized SinglevaluedIndex createSinglevaluedIndex( String name, EntryType keyType, EntryType valueType) throws StorageException { createIndex(name,keyType,valueType,true,true,false); return getSinglevaluedIndex(name); } // implement Storage public synchronized MultivaluedOrderedIndex createMultivaluedOrderedIndex( String name, EntryType keyType, EntryType valueType, boolean unique) throws StorageException { // NOTE: ignore unique because it appears to lie createIndex(name,keyType,valueType,false,false,true); return getMultivaluedOrderedIndex(name); } // implement Storage public synchronized MultivaluedIndex createMultivaluedIndex( String name, EntryType keyType, EntryType valueType, boolean unique) throws StorageException { createIndex(name,keyType,valueType,false,unique,false); return getMultivaluedIndex(name); } private String getDataType(EntryType entryType) { return (String) entryTypeToDataTypeMap.get(entryType); } private EntryType getEntryType(ResultSetMetaData md,int i) throws SQLException { String colName = md.getColumnName(i).toUpperCase(); int lastUnderscore = colName.lastIndexOf('_'); String entryTypeName = colName.substring(lastUnderscore + 1); return EntryType.decodeEntryType(entryTypeName); } private String stripMofId(String indexName) { int i = indexName.indexOf(storageId); if (i == -1) { return indexName; } int j = i + storageId.length(); if (indexName.charAt(j) != ':') { return indexName; } int n = indexName.length(); for (++j; j < n; ++j) { if (indexName.charAt(j) != '0') { break; } } return indexName.substring(0,i) + indexName.substring(j); } private String getTableNameForIndex(String indexName) { // Assume we're getting something of the form // |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.