001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jca.cci.core.support;
018
019import javax.resource.cci.Connection;
020import javax.resource.cci.ConnectionFactory;
021import javax.resource.cci.ConnectionSpec;
022
023import org.springframework.dao.support.DaoSupport;
024import org.springframework.jca.cci.CannotGetCciConnectionException;
025import org.springframework.jca.cci.connection.ConnectionFactoryUtils;
026import org.springframework.jca.cci.core.CciTemplate;
027import org.springframework.lang.Nullable;
028import org.springframework.util.Assert;
029
030/**
031 * Convenient super class for CCI-based data access objects.
032 *
033 * <p>Requires a {@link javax.resource.cci.ConnectionFactory} to be set,
034 * providing a {@link org.springframework.jca.cci.core.CciTemplate} based
035 * on it to subclasses through the {@link #getCciTemplate()} method.
036 *
037 * <p>This base class is mainly intended for CciTemplate usage but can
038 * also be used when working with a Connection directly or when using
039 * {@code org.springframework.jca.cci.object} classes.
040 *
041 * @author Thierry Templier
042 * @author Juergen Hoeller
043 * @since 1.2
044 * @see #setConnectionFactory
045 * @see #getCciTemplate
046 * @see org.springframework.jca.cci.core.CciTemplate
047 */
048public abstract class CciDaoSupport extends DaoSupport {
049
050        @Nullable
051        private CciTemplate cciTemplate;
052
053
054        /**
055         * Set the ConnectionFactory to be used by this DAO.
056         */
057        public final void setConnectionFactory(ConnectionFactory connectionFactory) {
058                if (this.cciTemplate == null || connectionFactory != this.cciTemplate.getConnectionFactory()) {
059                        this.cciTemplate = createCciTemplate(connectionFactory);
060                }
061        }
062
063        /**
064         * Create a CciTemplate for the given ConnectionFactory.
065         * Only invoked if populating the DAO with a ConnectionFactory reference!
066         * <p>Can be overridden in subclasses to provide a CciTemplate instance
067         * with different configuration, or a custom CciTemplate subclass.
068         * @param connectionFactory the CCI ConnectionFactory to create a CciTemplate for
069         * @return the new CciTemplate instance
070         * @see #setConnectionFactory(javax.resource.cci.ConnectionFactory)
071         */
072        protected CciTemplate createCciTemplate(ConnectionFactory connectionFactory) {
073                return new CciTemplate(connectionFactory);
074        }
075
076        /**
077         * Return the ConnectionFactory used by this DAO.
078         */
079        @Nullable
080        public final ConnectionFactory getConnectionFactory() {
081                return (this.cciTemplate != null ? this.cciTemplate.getConnectionFactory() : null);
082        }
083
084        /**
085         * Set the CciTemplate for this DAO explicitly,
086         * as an alternative to specifying a ConnectionFactory.
087         */
088        public final void setCciTemplate(CciTemplate cciTemplate) {
089                this.cciTemplate = cciTemplate;
090        }
091
092        /**
093         * Return the CciTemplate for this DAO,
094         * pre-initialized with the ConnectionFactory or set explicitly.
095         */
096        @Nullable
097        public final CciTemplate getCciTemplate() {
098                return this.cciTemplate;
099        }
100
101        @Override
102        protected final void checkDaoConfig() {
103                if (this.cciTemplate == null) {
104                        throw new IllegalArgumentException("'connectionFactory' or 'cciTemplate' is required");
105                }
106        }
107
108
109        /**
110         * Obtain a CciTemplate derived from the main template instance,
111         * inheriting the ConnectionFactory and other settings but
112         * overriding the ConnectionSpec used for obtaining Connections.
113         * @param connectionSpec the CCI ConnectionSpec that the returned
114         * template instance is supposed to obtain Connections for
115         * @return the derived template instance
116         * @see org.springframework.jca.cci.core.CciTemplate#getDerivedTemplate(javax.resource.cci.ConnectionSpec)
117         */
118        protected final CciTemplate getCciTemplate(ConnectionSpec connectionSpec) {
119                CciTemplate cciTemplate = getCciTemplate();
120                Assert.state(cciTemplate != null, "No CciTemplate set");
121                return cciTemplate.getDerivedTemplate(connectionSpec);
122        }
123
124        /**
125         * Get a CCI Connection, either from the current transaction or a new one.
126         * @return the CCI Connection
127         * @throws org.springframework.jca.cci.CannotGetCciConnectionException
128         * if the attempt to get a Connection failed
129         * @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
130         */
131        protected final Connection getConnection() throws CannotGetCciConnectionException {
132                ConnectionFactory connectionFactory = getConnectionFactory();
133                Assert.state(connectionFactory != null, "No ConnectionFactory set");
134                return ConnectionFactoryUtils.getConnection(connectionFactory);
135        }
136
137        /**
138         * Close the given CCI Connection, created via this bean's ConnectionFactory,
139         * if it isn't bound to the thread.
140         * @param con the Connection to close
141         * @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#releaseConnection
142         */
143        protected final void releaseConnection(Connection con) {
144                ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
145        }
146
147}