From: <db...@us...> - 2003-03-02 15:28:16
|
Update of /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/jca In directory sc8-pr-cvs1:/tmp/cvs-serv22624/src/net/sf/hibernate/jca Added Files: JCASessionImpl.java ManagedConnectionImpl.java JCASessionFactoryImpl.java LocalTransactionImpl.java ManagedConnectionFactoryImpl.java MetaDataImpl.java ConnectionRequestInfoImpl.java hibernate-service.xml Log Message: initial commit of JCA 1.0 impl --- NEW FILE: JCASessionImpl.java --- // $Id$ package net.sf.hibernate.jca; import java.io.Serializable; import java.sql.Connection; import java.util.Collection; import java.util.Iterator; import java.util.List; import net.sf.hibernate.FlushMode; import net.sf.hibernate.HibernateException; import net.sf.hibernate.LockMode; import net.sf.hibernate.Query; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; import net.sf.hibernate.type.Type; public class JCASessionImpl implements Session { private Session session; private ManagedConnectionImpl mc; public JCASessionImpl(Session session, ManagedConnectionImpl mc){ this.session = session; this.mc = mc; } public void flush() throws HibernateException { session.flush(); } public void setFlushMode(FlushMode flushMode) { session.setFlushMode(flushMode); } public FlushMode getFlushMode() { return session.getFlushMode(); } public Connection connection() throws HibernateException { return session.connection(); } public Connection disconnect() throws HibernateException { return session.disconnect(); } public void reconnect() throws HibernateException { session.reconnect(); } public void reconnect(Connection connection) throws HibernateException { session.reconnect(connection); } public Connection close() throws HibernateException { mc.closeHandle(this); mc = null; return session.close(); } public boolean isOpen() { return session.isOpen(); } /** * @see net.sf.hibernate.Session#isConnected() */ public boolean isConnected() { return session.isConnected(); } /** * @see net.sf.hibernate.Session#getIdentifier(Object) */ public Serializable getIdentifier(Object object) throws HibernateException { return session.getIdentifier(object); } /** * @see net.sf.hibernate.Session#load(Class, Serializable, LockMode) */ public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException { return session.load(theClass, id, lockMode); } /** * @see net.sf.hibernate.Session#load(Class, Serializable) */ public Object load(Class theClass, Serializable id) throws HibernateException { return session.load(theClass, id); } /** * @see net.sf.hibernate.Session#load(Object, Serializable) */ public void load(Object object, Serializable id) throws HibernateException { session.load(object, id); } /** * @see net.sf.hibernate.Session#save(Object) */ public Serializable save(Object object) throws HibernateException { return session.save(object); } /** * @see net.sf.hibernate.Session#save(Object, Serializable) */ public void save(Object object, Serializable id) throws HibernateException { session.save(object, id); } /** * @see net.sf.hibernate.Session#saveOrUpdate(Object) */ public void saveOrUpdate(Object object) throws HibernateException { session.saveOrUpdate(object); } /** * @see net.sf.hibernate.Session#update(Object) */ public void update(Object object) throws HibernateException { session.update(object); } /** * @see net.sf.hibernate.Session#update(Object, Serializable) */ public void update(Object object, Serializable id) throws HibernateException { session.update(object, id); } public void delete(Object object) throws HibernateException { session.delete(object); } public List find(String query) throws HibernateException { return session.find(query); } public List find(String query, Object value, Type type) throws HibernateException { return session.find(query, value, type); } public List find(String query, Object[] values, Type[] types) throws HibernateException { return session.find(query, values, types); } public Iterator iterate(String query) throws HibernateException { return session.iterate(query); } public Iterator iterate(String query, Object value, Type type) throws HibernateException { return session.iterate(query, value, type); } public Iterator iterate(String query, Object[] values, Type[] types) throws HibernateException { return session.iterate(query, values, types); } public Collection filter(Object collection, String filter) throws HibernateException { return session.filter(collection, filter); } public Collection filter( Object collection, String filter, Object value, Type type) throws HibernateException { return null; } public Collection filter( Object collection, String filter, Object[] values, Type[] types) throws HibernateException { return session.filter(collection, filter, values, types); } public int delete(String query) throws HibernateException { return session.delete(query); } public int delete(String query, Object value, Type type) throws HibernateException { return session.delete(query, value, type); } public int delete(String query, Object[] values, Type[] types) throws HibernateException { return session.delete(query, values, types); } public void lock(Object object, LockMode lockMode) throws HibernateException { session.lock(object, lockMode); } public void refresh(Object object) throws HibernateException { session.refresh(object); } public LockMode getCurrentLockMode(Object object) throws HibernateException { return session.getCurrentLockMode(object); } public Transaction beginTransaction() throws HibernateException { return session.beginTransaction(); } public Query createQuery(String queryString) throws HibernateException { return session.createQuery(queryString); } public Query createFilter(Object collection, String queryString) throws HibernateException { return session.createFilter(collection, queryString); } public Query getNamedQuery(String queryName) throws HibernateException { return session.getNamedQuery(queryName); } void setManagedConnection(ManagedConnectionImpl mc){ this.mc = mc; } } --- NEW FILE: ManagedConnectionImpl.java --- // $Id$ package net.sf.hibernate.jca; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; import java.util.Set; import javax.resource.NotSupportedException; import javax.resource.ResourceException; import javax.resource.spi.ConnectionEvent; import javax.resource.spi.ConnectionEventListener; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.IllegalStateException; import javax.resource.spi.LocalTransaction; import javax.resource.spi.ManagedConnection; import javax.resource.spi.ManagedConnectionFactory; import javax.resource.spi.ManagedConnectionMetaData; import javax.security.auth.Subject; import javax.transaction.xa.XAResource; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Implementation of JCA Managed Connection. The underlying connection is a java.sql.Connecion object * which is passed to a Hibernate session object for the client to use. * * This is based on a JBoss LPGL generic JDBC JCA implementation * * Currently only supports LocalTransactions (XA should follow at some stage) * */ public class ManagedConnectionImpl implements ManagedConnection { private static final Log log = LogFactory.getLog(ManagedConnectionImpl.class); // true if connection has been destroyed private boolean destroyed; // the factory that created this managed connection private ManagedConnectionFactory mcf; // as per JCA 1.0 spec 5.6 when this is not null then logging has been enabled // by the application server and we log to this writer private PrintWriter logWriter; // factory to create sessions private SessionFactory sessions; // underlying connection to the database private Connection connection; // registered listeners from the application server private final Collection listeners = new ArrayList(); // a set of JCASessionImpl handles associated with this managed connection private final Set handles = new HashSet(); private Properties props; ManagedConnectionImpl( ManagedConnectionFactory mcf, String user, Properties props, SessionFactory sessions, Connection connection) { log.trace("Constructor called with user " + user); this.mcf = mcf; this.sessions = sessions; this.connection = connection; this.props = props; } /** * Creates and returns a new Hibernate Session * * Will throw a ResourceException if the session factory * fails to create a session */ public Object getConnection( Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException { log.trace( "getConnection called with subject[" + subject + " ] connection request info[" + connectionRequestInfo + "]"); // maybe should check the credentials match up with the current connection? // create session from the session factory Session session = null; try { session = sessions.openSession(connection); } catch (Exception hbe) { log.error( "Error opening session with connection " + connection, hbe); throw new ResourceException(hbe.getMessage()); } JCASessionImpl jcaSession = new JCASessionImpl(session, this); // add the session handle to the collection of handles on this connection synchronized (handles) { handles.add(jcaSession); } if (log.isDebugEnabled()) { log.debug( "Added session handle - " + jcaSession + " to handles now at size " + handles.size()); } return jcaSession; } /** * Closes the connection to the database * * @throws ResourceException cannot close connection (with the linked exception) */ public void destroy() throws ResourceException { if (log.isTraceEnabled()) { log.trace("destroy called on " + this); } if (connection == null) throw new IllegalStateException("Resource cannot be destroyed because it is null"); try { if (connection.isClosed()) throw new IllegalStateException("Resource cannot be destroyed because it is already closed"); connection.close(); connection = null; } catch (SQLException ex) { log.error("Error closing connection - " + connection, ex); ResourceException re = new ResourceException("Exception trying to close connection"); re.setLinkedException(ex); throw re; } finally { destroyed = true; } } /** * Cleans up connection handles so they can't be used again * But the physical connection is kept open */ public void cleanup() throws ResourceException { if (log.isTraceEnabled()) { log.trace("cleanup called on " + this); } synchronized (handles) { for (Iterator i = handles.iterator(); i.hasNext();) { JCASessionImpl lc = (JCASessionImpl) i.next(); lc.setManagedConnection(null); } handles.clear(); } } /** * Associates the session handle with this managed connection */ public void associateConnection(Object handle) throws ResourceException { if (!(handle instanceof JCASessionImpl)) { throw new ResourceException( "Wrong kind of connection handle to associate " + handle); } ((JCASessionImpl) handle).setManagedConnection(this); synchronized (handles) { handles.add(handle); } } public void addConnectionEventListener(ConnectionEventListener listener) { synchronized (listeners) { listeners.add(listener); } } public void removeConnectionEventListener(ConnectionEventListener listener) { synchronized (listeners) { listeners.remove(listener); } } /** * NOT SUPPORTED * @throws NotSupportedException */ public XAResource getXAResource() throws ResourceException { throw new NotSupportedException("XA transaction not supported"); } public LocalTransaction getLocalTransaction() throws ResourceException { return new LocalTransactionImpl(this); } public ManagedConnectionMetaData getMetaData() throws ResourceException { return new MetaDataImpl(this); } public void setLogWriter(PrintWriter out) throws ResourceException { this.logWriter = out; } public PrintWriter getLogWriter() throws ResourceException { return logWriter; } public Properties getProps() { return props; } public void setProps(Properties props) { this.props = props; } // package private level methods ManagedConnectionFactory getManagedConnectionFactory() { return mcf; } void closeHandle(Session handle) { // remove the handle from the collection safely synchronized (handles) { handles.remove(handle); } // create a connection closed event and send ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED); ce.setConnectionHandle(handle); sendEvent(ce); } Connection getConnection() { return connection; } void sendEvent(final ConnectionEvent event) { int type = event.getId(); if (log.isDebugEnabled()) { log.debug("Sending connection event: " + type); } // convert to an array to avoid concurrent modification exceptions ConnectionEventListener[] list = (ConnectionEventListener[]) listeners.toArray( new ConnectionEventListener[listeners.size()]); for (int i = 0; i < list.length; i++) { switch (type) { case ConnectionEvent.CONNECTION_CLOSED : list[i].connectionClosed(event); break; case ConnectionEvent.LOCAL_TRANSACTION_STARTED : list[i].localTransactionStarted(event); break; case ConnectionEvent.LOCAL_TRANSACTION_COMMITTED : list[i].localTransactionCommitted(event); break; case ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK : list[i].localTransactionRolledback(event); break; case ConnectionEvent.CONNECTION_ERROR_OCCURRED : list[i].connectionErrorOccurred(event); break; default : throw new IllegalArgumentException( "Illegal eventType: " + type); } } } } --- NEW FILE: JCASessionFactoryImpl.java --- //$Id: SessionImpl.java,v 1.22 2003/02/19 02:02:10 oneovthafew Exp $ package net.sf.hibernate.jca; import java.sql.Connection; import java.util.Map; import java.util.Properties; import javax.naming.NamingException; import javax.naming.Reference; import javax.resource.Referenceable; import javax.resource.ResourceException; import javax.resource.spi.ConnectionManager; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.ManagedConnectionFactory; import net.sf.hibernate.Databinder; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Interceptor; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.cfg.Configuration; import net.sf.hibernate.cfg.Environment; import net.sf.hibernate.metadata.ClassMetadata; import net.sf.hibernate.metadata.CollectionMetadata; import net.sf.hibernate.util.PropertiesHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public final class JCASessionFactoryImpl implements SessionFactory, Referenceable { private static final Log log = LogFactory.getLog(JCASessionFactoryImpl.class); private SessionFactory factory; private ManagedConnectionFactory managedFactory; private ConnectionManager cxManager; private Reference reference; public JCASessionFactoryImpl(ManagedConnectionFactory mcf, String dialect, String mapResources) throws HibernateException { this(mcf, null, dialect, mapResources); } public JCASessionFactoryImpl( ManagedConnectionFactory managedFactory, ConnectionManager cxManager, String dialect, String mapResources) throws HibernateException { Properties hibProperties = new Properties(); hibProperties.setProperty(Environment.DIALECT, dialect); Configuration cfg = new Configuration().addProperties(hibProperties); // taken from HibernateService, maybe factor out for JCA 1.5 String[] mappingFiles = PropertiesHelper.toStringArray(mapResources, " ,\n\t\r\f"); for ( int i=0; i<mappingFiles.length; i++ ) { cfg.addResource( mappingFiles[i], Thread.currentThread().getContextClassLoader() ); } this.managedFactory = managedFactory; this.factory = cfg.buildSessionFactory(); this.cxManager = cxManager; } public void close() throws HibernateException { factory.close(); } public Map getAllClassMetadata() throws HibernateException { return factory.getAllClassMetadata(); } public Map getAllCollectionMetadata() throws HibernateException { return factory.getAllCollectionMetadata(); } public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException { return factory.getClassMetadata(persistentClass); } public CollectionMetadata getCollectionMetadata(String roleName) throws HibernateException { return factory.getCollectionMetadata(roleName); } public Databinder openDatabinder() throws HibernateException { return factory.openDatabinder(); } public Session openSession() throws HibernateException { Session result = null; try { ConnectionRequestInfo info = new ConnectionRequestInfoImpl(factory); result = (Session) cxManager.allocateConnection(managedFactory, info); } catch (ResourceException re) { throw new HibernateException(re); } return result; } public Session openSession( Connection connection, Interceptor interceptor) { return factory.openSession(connection, interceptor); } public Session openSession(Connection connection) { return factory.openSession(connection); } public Session openSession(Interceptor interceptor) throws HibernateException { return factory.openSession(interceptor); } public Reference getReference() throws NamingException { return reference; } public void setReference(Reference ref) { reference = ref; } } --- NEW FILE: LocalTransactionImpl.java --- // $Id$ package net.sf.hibernate.jca; import java.sql.SQLException; import javax.jms.JMSException; import javax.resource.ResourceException; import javax.resource.spi.ConnectionEvent; import javax.resource.spi.EISSystemException; import javax.resource.spi.LocalTransaction; /** * Simple implementation of a location transaction for the moment. * * Basically delagates to the connection for commit and rollback * * Will set autocommit to false on the begin() * * Must clarify the Exception handling / messages / linked exceptions still */ public class LocalTransactionImpl implements LocalTransaction { protected ManagedConnectionImpl mc; public LocalTransactionImpl(final ManagedConnectionImpl mc) { this.mc = mc; } public void begin() throws ResourceException { try { mc.getConnection().setAutoCommit(false); } catch (SQLException ex) { ResourceException re = new EISSystemException( "Could not begin LocalTransaction : " + ex.getMessage()); re.setLinkedException(ex); throw re; } } public void commit() throws ResourceException { try { mc.getConnection().commit(); } catch (SQLException ex) { ResourceException re = new EISSystemException( "Could not commit LocalTransaction : " + ex.getMessage()); re.setLinkedException(ex); throw re; } } public void rollback() throws ResourceException { try { mc.getConnection().rollback(); } catch (SQLException ex) { ResourceException re = new EISSystemException( "Could not rollback LocalTransaction : " + ex.getMessage()); re.setLinkedException(ex); throw re; } } } --- NEW FILE: ManagedConnectionFactoryImpl.java --- package net.sf.hibernate.jca; import java.io.PrintWriter; import java.io.Serializable; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.util.Iterator; import java.util.Properties; import java.util.Set; import javax.resource.NotSupportedException; import javax.resource.ResourceException; import javax.resource.spi.ConnectionManager; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.ManagedConnection; import javax.resource.spi.ManagedConnectionFactory; import javax.resource.spi.security.PasswordCredential; import javax.security.auth.Subject; import net.sf.hibernate.HibernateException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Factory for creating Factories, connections and matching connections * * Does not currently support unmanaged environments */ public class ManagedConnectionFactoryImpl implements ManagedConnectionFactory, Serializable { private static final Log log = LogFactory.getLog(ManagedConnectionFactoryImpl.class); private String connectionURL; private String driverClass; private String userName; private String password; private int transactionIsolation = -1; private String dialect; private String mapResources; private Properties connectionProperties = new Properties(); private PrintWriter out; private boolean driverLoaded; public ManagedConnectionFactoryImpl() { } /** * Creates a Hibernate SessionFactory for the container * * @throws ResourceException can't create Session Factory (thrown with linked exception) */ public Object createConnectionFactory(ConnectionManager cxManager) throws ResourceException { log("createConnectionFactory with connection manager - " + cxManager); Object obj = null; try { obj = new JCASessionFactoryImpl(this, cxManager, dialect, mapResources); } catch (HibernateException hbe) { log( "Got Hibernate exception when trying to create Connection Factory", hbe); ResourceException re = new ResourceException("Got Hibernate exception when trying to create Connection Factory"); re.setLinkedException(hbe); throw re; } return obj; } /** * NOT SUPPORTED * * @throws NotSupportedException Unmanaged environments are not currently supported */ public Object createConnectionFactory() throws ResourceException { throw new NotSupportedException("Resource Adapter does not support an un-managed environment"); } /** * Creates a ManagedConnection and physically a connection to the database * * Currently only uses username, password, driver class and URL * * Need to include mapping files, isolation level, dialect etc * * @throws ResourceException cannot get connection to database */ public ManagedConnection createManagedConnection( Subject subject, ConnectionRequestInfo info) throws ResourceException { log("createManagedConnection called"); try { // Also taken from JBoss JDBC JCA Impl Properties props = getConnectionProperties(subject, info); // Some friendly drivers (Oracle, you guessed right) modify the props you supply. // Since we use our copy to identify compatibility in matchManagedConnection, we need // a pristine copy for our own use. So give the friendly driver a copy. Properties copy = new Properties(); copy.putAll(props); String url = internalGetConnectionURL(); checkDriver(url); Connection con = DriverManager.getConnection(url, copy); // wait for the begin transaction to turn auto commit off? //con.setAutoCommit(false); return new ManagedConnectionImpl( this, userName, props, ((ConnectionRequestInfoImpl) info).getSessionFactory(), con); } catch (Exception ex) { log("Got exception when trying to create Managed Connection", ex); ResourceException re = new ResourceException("Got exception when trying to create Managed Connection"); re.setLinkedException(ex); throw re; } } public void setLogWriter(PrintWriter out) throws ResourceException { this.out = out; } public PrintWriter getLogWriter() throws ResourceException { return this.out; } public ManagedConnection matchManagedConnections( Set mcs, Subject subject, ConnectionRequestInfo cri) throws ResourceException { Properties newProps = getConnectionProperties(subject, cri); for (Iterator i = mcs.iterator(); i.hasNext();) { Object o = i.next(); if (o instanceof ManagedConnectionImpl) { ManagedConnectionImpl mc = (ManagedConnectionImpl) o; if (mc.getProps().equals(newProps) /*&& mc.checkValid()*/ ) // JBoss method to check validity of connection by executing some SQL { return mc; } // end of if () } // end of if () } // end of for () return null; } /** * * @return hashcode computed according to recommendations in Effective Java. */ public int hashCode() { int result = 17; result = result * 37 + ((connectionURL == null) ? 0 : connectionURL.hashCode()); result = result * 37 + ((driverClass == null) ? 0 : driverClass.hashCode()); result = result * 37 + ((userName == null) ? 0 : userName.hashCode()); result = result * 37 + ((password == null) ? 0 : password.hashCode()); result = result * 37 + ((dialect == null) ? 0 : dialect.hashCode()); result = result * 37 + ((mapResources == null) ? 0 : mapResources.hashCode()); result = result * 37 + transactionIsolation; return result; } /** * * @param param1 <description> * @return <description> */ public boolean equals(Object other) { if (this == other) { return true; } // end of if () if (getClass() != other.getClass()) { return false; } // end of if () ManagedConnectionFactoryImpl otherMcf = (ManagedConnectionFactoryImpl) other; return this.connectionURL.equals(otherMcf.connectionURL) && this.driverClass.equals(otherMcf.driverClass) && ((this.mapResources == null) ? otherMcf.mapResources == null : this.mapResources.equals(otherMcf.mapResources)) && ((this.dialect == null) ? otherMcf.dialect == null : this.dialect.equals(otherMcf.dialect)) && ((this.userName == null) ? otherMcf.userName == null : this.userName.equals(otherMcf.userName)) && ((this.password == null) ? otherMcf.password == null : this.password.equals(otherMcf.password)) && this.transactionIsolation == otherMcf.transactionIsolation; } public String getDriverClass() { return driverClass; } public String getPassword() { return password; } public String getUserName() { return userName; } public void setDriverClass(String driverClass) { this.driverClass = driverClass; this.driverLoaded = false; } public void setPassword(String password) { this.password = password; } public void setUserName(String username) { this.userName = username; } public String getConnectionURL() { return connectionURL; } public void setConnectionURL(String url) { this.connectionURL = url; } public String getDialect() { return dialect; } public void setDialect(String dialect) { this.dialect = dialect; } public String getMapResources() { return mapResources; } public void setMapResources(String mapResources) { this.mapResources = mapResources; } public Properties getConnectionProperties() { return connectionProperties; } public void setConnectionProperties(Properties connectionProperties) { this.connectionProperties = connectionProperties; } public String getTransactionIsolation() { switch (this.transactionIsolation) { case Connection.TRANSACTION_NONE : return "TRANSACTION_NONE"; case Connection.TRANSACTION_READ_COMMITTED : return "TRANSACTION_READ_COMMITTED"; case Connection.TRANSACTION_READ_UNCOMMITTED : return "TRANSACTION_READ_UNCOMMITTED"; case Connection.TRANSACTION_REPEATABLE_READ : return "TRANSACTION_REPEATABLE_READ"; case Connection.TRANSACTION_SERIALIZABLE : return "TRANSACTION_SERIALIZABLE"; case -1 : return "DEFAULT"; default : return Integer.toString(transactionIsolation); } } public void setTransactionIsolation(String transactionIsolation) { if (transactionIsolation.equals("TRANSACTION_NONE")) { this.transactionIsolation = Connection.TRANSACTION_NONE; } else if (transactionIsolation.equals("TRANSACTION_READ_COMMITTED")) { this.transactionIsolation = Connection.TRANSACTION_READ_COMMITTED; } else if ( transactionIsolation.equals("TRANSACTION_READ_UNCOMMITTED")) { this.transactionIsolation = Connection.TRANSACTION_READ_UNCOMMITTED; } else if ( transactionIsolation.equals("TRANSACTION_REPEATABLE_READ")) { this.transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ; } else if (transactionIsolation.equals("TRANSACTION_SERIALIZABLE")) { this.transactionIsolation = Connection.TRANSACTION_SERIALIZABLE; } else { try { this.transactionIsolation = Integer.parseInt(transactionIsolation); } catch (NumberFormatException nfe) { throw new IllegalArgumentException( "Setting Isolation level to unknown state: " + transactionIsolation); } } } private void log(String message) { log(message, null); } private void log(String message, Throwable t) { // log to provided output if set by app server // assumes to log error if an exception is provided if (out != null) { out.write(message); if (t != null) t.printStackTrace(out); } if (t != null) { log.error(message, t); } else { log.info(message); } } // taken from JBoss JCA impl /** * Check the driver for the given URL. If it is not registered already * then register it. * * @param url The JDBC URL which we need a driver for. */ protected void checkDriver(final String url) throws ResourceException { // don't bother if it is loaded already if (driverLoaded) { return; } log.debug("Checking driver for URL: " + url); if (driverClass == null) { throw new ResourceException("No Driver class specified!"); } // Check if the driver is already loaded, if not then try to load it if (isDriverLoadedForURL(url)) { driverLoaded = true; return; } // end of if () try { //try to load the class... this should register with DriverManager. Class clazz = Thread.currentThread().getContextClassLoader().loadClass( driverClass); if (isDriverLoadedForURL(url)) { driverLoaded = true; //return immediately, some drivers (Cloudscape) do not let you create an instance. return; } // end of if () //We loaded the class, but either it didn't register //and is not spec compliant, or is the wrong class. Driver driver = (Driver) clazz.newInstance(); DriverManager.registerDriver(driver); if (isDriverLoadedForURL(url)) { driverLoaded = true; return; } // end of if () //We can even instantiate one, it must be the wrong class for the URL. } catch (Exception e) { ResourceException re = new ResourceException( "Failed to register driver for: " + driverClass); re.setLinkedException(e); throw re; } throw new ResourceException( "Apparently wrong driver class specified for URL: class: " + driverClass + ", url: " + url); } private boolean isDriverLoadedForURL(String url) { try { DriverManager.getDriver(url); log.debug("Driver already registered for url: " + url); return true; } catch (Exception e) { log.debug("Driver not yet registered for url: " + url); return false; } // end of try-catch } protected String internalGetConnectionURL() { return connectionURL; } /** * Gets full set of connection properties, i.e. whatever is provided * in config plus "user" and "password" from subject/cri. * * <p>Note that the set is used to match connections to datasources as well * as to create new managed connections. * * <p>In fact, we have a problem here. Theoretically, there is a possible * name collision between config properties and "user"/"password". */ protected Properties getConnectionProperties( Subject subject, ConnectionRequestInfo cri) throws ResourceException { if (cri != null && cri.getClass() != ConnectionRequestInfoImpl.class) { throw new ResourceException( "Wrong kind of ConnectionRequestInfo: " + cri.getClass()); } // end of if () Properties props = new Properties(); props.putAll(connectionProperties); if (subject != null) { for (Iterator i = subject.getPrivateCredentials().iterator(); i.hasNext(); ) { Object o = i.next(); if (o instanceof PasswordCredential && ((PasswordCredential) o) .getManagedConnectionFactory() .equals( this)) { PasswordCredential cred = (PasswordCredential) o; props.setProperty( "user", (cred.getUserName() == null) ? "" : cred.getUserName()); props.setProperty( "password", new String(cred.getPassword())); return props; } // end of if () } // end of for () throw new ResourceException("No matching credentials in Subject!"); } // end of if () ConnectionRequestInfoImpl lcri = (ConnectionRequestInfoImpl) cri; if (lcri != null) { props.setProperty( "user", (lcri.getUserName() == null) ? "" : lcri.getUserName()); props.setProperty( "password", (lcri.getPassword() == null) ? "" : lcri.getPassword()); return props; } // end of if () if (userName != null) { props.setProperty("user", userName); props.setProperty("password", (password == null) ? "" : password); } return props; } } --- NEW FILE: MetaDataImpl.java --- package net.sf.hibernate.jca; import java.sql.SQLException; import javax.resource.ResourceException; import javax.resource.spi.EISSystemException; import javax.resource.spi.IllegalStateException; import javax.resource.spi.ManagedConnectionMetaData; /** * * Implementation delegates to the database connection meta data object * * All methods will throw IllegalStateException if the managed connection * has already been destroyed * */ public class MetaDataImpl implements ManagedConnectionMetaData { private ManagedConnectionImpl mc; public MetaDataImpl(ManagedConnectionImpl mc) { this.mc = mc; } public String getEISProductName() throws ResourceException { String result = null; try { result = mc.getConnection().getMetaData().getUserName(); } catch (SQLException e) { throw new EISSystemException(e.getMessage()); } return result; } public String getEISProductVersion() throws ResourceException { String result = null; try { result = mc.getConnection().getMetaData().getDriverVersion(); } catch (SQLException e) { throw new EISSystemException(e.getMessage()); } return result; } public int getMaxConnections() throws ResourceException { int result = 0; try { result = mc.getConnection().getMetaData().getMaxConnections(); } catch (SQLException e) { throw new EISSystemException(e.getMessage()); } return result; } public String getUserName() throws ResourceException { String result = null; try { result = mc.getConnection().getMetaData().getUserName(); } catch (SQLException e) { throw new EISSystemException(e.getMessage()); } return result; } } --- NEW FILE: ConnectionRequestInfoImpl.java --- package net.sf.hibernate.jca; import javax.resource.spi.ConnectionRequestInfo; import net.sf.hibernate.SessionFactory; public class ConnectionRequestInfoImpl implements ConnectionRequestInfo { private SessionFactory sessions; private String userName; private String password; public ConnectionRequestInfoImpl(SessionFactory sessions) { this.sessions = sessions; } public SessionFactory getSessionFactory(){ return sessions; } public boolean equals(Object obj) { if (obj == null) return false; if (obj instanceof ConnectionRequestInfoImpl) { ConnectionRequestInfoImpl other = (ConnectionRequestInfoImpl) obj; return (isEqual(this.sessions, other.sessions)); } else { return false; } } public int hashCode() { return sessions.hashCode(); } private boolean isEqual(Object o1, Object o2) { if (o1 == null) { return (o2 == null); } else { return o1.equals(o2); } } /** * Returns the password. * @return String */ public String getPassword() { return password; } /** * Returns the userName. * @return String */ public String getUserName() { return userName; } /** * Sets the password. * @param password The password to set */ public void setPassword(String password) { this.password = password; } /** * Sets the userName. * @param userName The userName to set */ public void setUserName(String userName) { this.userName = userName; } } --- NEW FILE: hibernate-service.xml --- <?xml version="1.0" encoding="UTF-8"?> <!-- ===================================================================== --> <!-- --> <!-- JBoss Server Configuration --> <!-- --> <!-- ===================================================================== --> <server> <!-- ==================================================================== --> <!-- New ConnectionManager setup for mysql using 2.0.11 driver --> <!-- Build jmx-api (build/build.sh all) and view for config documentation --> <!-- ==================================================================== --> <mbean code="org.jboss.resource.connectionmanager.LocalTxConnectionManager" name="jboss.jca:service=LocalTxCM,name=Hibernate Resource Adapter"> <attribute name="JndiName">jca/test</attribute> <depends optional-attribute-name="ManagedConnectionFactoryName"> <!--embedded mbean--> <mbean code="org.jboss.resource.connectionmanager.RARDeployment" name="jboss.jca:service=LocalTxDS,name=Hibernate Resource Adapter"> <attribute name="ManagedConnectionFactoryProperties"> <properties> <config-property> <config-property-name>ConnectionURL</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>jdbc:mysql:///test</config-property-value> </config-property> <config-property> <config-property-name>DriverClass</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>com.mysql.jdbc.Driver</config-property-value> </config-property> <config-property> <config-property-name>Password</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value></config-property-value> </config-property> <config-property> <config-property-name>UserName</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>dbradby</config-property-value> </config-property> <config-property> <config-property-name>Dialect</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>net.sf.hibernate.dialect.MySQLDialect</config-property-value> </config-property> <config-property> <config-property-name>MapResources</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>Simple.hbm.xml</config-property-value> </config-property> </properties> </attribute> <!--Below here are advanced properties --> <!--hack--> <depends optional-attribute-name="OldRarDeployment">jboss.jca:service=RARDeployment,name=Hibernate Resource Adapter</depends> </mbean> </depends> <depends optional-attribute-name="ManagedConnectionPool"> <!--embedded mbean--> <mbean code="org.jboss.resource.connectionmanager.JBossManagedConnectionPool" name="jboss.jca:service=LocalTxPool,name=Hibernate Resource Adapter"> <attribute name="MinSize">0</attribute> <attribute name="MaxSize">50</attribute> <attribute name="BlockingTimeoutMillis">5000</attribute> <attribute name="IdleTimeoutMinutes">15</attribute> <!--criteria indicates if Subject (from security domain) or app supplied parameters (such as from getConnection(user, pw)) are used to distinguish connections in the pool. Choices are ByContainerAndApplication (use both), ByContainer (use Subject), ByApplication (use app supplied params only), ByNothing (all connections are equivalent, usually if adapter supports reauthentication)--> <attribute name="Criteria">ByContainer</attribute> </mbean> </depends> <depends optional-attribute-name="CachedConnectionManager">jboss.jca:service=CachedConnectionManager</depends> <depends optional-attribute-name="JaasSecurityManagerService">jboss.security:service=JaasSecurityManager</depends> <!--make the rar deploy! hack till better deployment--> <depends>jboss.jca:service=RARDeployer</depends> <attribute name="TransactionManager">java:/TransactionManager</attribute> </mbean> </server> |