001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
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 *     http://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 * Contributors:
017 *     Florent Guillaume
018 */
019
020package org.nuxeo.ecm.core.storage.sql.ra;
021
022import java.util.Calendar;
023
024import javax.naming.Reference;
025import javax.resource.ResourceException;
026import javax.resource.cci.ConnectionSpec;
027import javax.resource.cci.RecordFactory;
028import javax.resource.cci.ResourceAdapterMetaData;
029import javax.resource.spi.ConnectionManager;
030
031import org.apache.commons.logging.LogFactory;
032import org.nuxeo.ecm.core.api.NuxeoException;
033import org.nuxeo.ecm.core.api.repository.FulltextConfiguration;
034import org.nuxeo.ecm.core.storage.sql.Repository;
035import org.nuxeo.ecm.core.storage.sql.Session;
036import org.nuxeo.ecm.core.storage.sql.coremodel.SQLSession;
037import org.nuxeo.runtime.jtajca.NuxeoConnectionManagerConfiguration;
038import org.nuxeo.runtime.jtajca.NuxeoContainer;
039import org.nuxeo.runtime.jtajca.NuxeoContainer.ConnectionManagerWrapper;
040
041/**
042 * The connection factory delegates connection requests to the application server {@link ConnectionManager}.
043 * <p>
044 * An instance of this class is returned to the application when a JNDI lookup is done.
045 *
046 * @author Florent Guillaume
047 */
048public class ConnectionFactoryImpl implements Repository, org.nuxeo.ecm.core.model.Repository {
049
050    private static final long serialVersionUID = 1L;
051
052    private final ManagedConnectionFactoryImpl managedConnectionFactory;
053
054    private final ConnectionManager connectionManager;
055
056    private final String name;
057
058    private Reference reference;
059
060    /**
061     * This is {@code true} if the connectionManager comes from an application server, or {@code false} if the
062     * {@link ConnectionFactoryImpl} was constructed by application code and passed our manual
063     * {@link ConnectionManagerImpl}.
064     */
065    @SuppressWarnings("unused")
066    private final boolean managed;
067
068    public ConnectionFactoryImpl(ManagedConnectionFactoryImpl managedConnectionFactory,
069            ConnectionManager connectionManager) {
070        this.managedConnectionFactory = managedConnectionFactory;
071        this.connectionManager = connectionManager;
072        managed = !(connectionManager instanceof ConnectionManagerImpl);
073        name = managedConnectionFactory.getName();
074    }
075
076    /*
077     * ----- javax.resource.cci.ConnectionFactory -----
078     */
079
080    /**
081     * Gets a new connection.
082     *
083     * @param connectionSpec the connection spec (unused)
084     * @return the connection
085     */
086    @Override
087    public Session getConnection(ConnectionSpec connectionSpec) {
088        return getConnection();
089    }
090
091    /**
092     * Gets a new connection.
093     *
094     * @return the connection
095     */
096    @Override
097    public Session getConnection() {
098        try {
099            return (Session) connectionManager.allocateConnection(managedConnectionFactory, null);
100        } catch (ResourceException e) {
101            String msg = e.getMessage();
102            if (msg != null && msg.startsWith("No ManagedConnections available")) {
103                String err = "Connection pool is fully used";
104                if (connectionManager instanceof ConnectionManagerWrapper) {
105                    ConnectionManagerWrapper cmw = (ConnectionManagerWrapper) connectionManager;
106                    NuxeoConnectionManagerConfiguration config = cmw.getConfiguration();
107                    err = err + ", consider increasing " + "nuxeo.vcs.blocking-timeout-millis (currently "
108                            + config.getBlockingTimeoutMillis() + ") or " + "nuxeo.vcs.max-pool-size (currently "
109                            + config.getMaxPoolSize() + ")";
110                }
111                throw new NuxeoException(err, e);
112            }
113            throw new NuxeoException(e);
114        }
115    }
116
117    @Override
118    public ResourceAdapterMetaData getMetaData() throws ResourceException {
119        // TODO Auto-generated method stub
120        throw new UnsupportedOperationException("Not implemented");
121    }
122
123    @Override
124    public RecordFactory getRecordFactory() throws ResourceException {
125        throw new UnsupportedOperationException("Not implemented");
126    }
127
128    /*
129     * ----- javax.naming.Referenceable -----
130     */
131
132    @Override
133    public Reference getReference() {
134        return reference;
135    }
136
137    @Override
138    public void setReference(Reference reference) {
139        this.reference = reference;
140    }
141
142    /*
143     * ----- Repository -----
144     */
145
146    @Override
147    public void close() {
148        throw new UnsupportedOperationException("Not implemented");
149    }
150
151    /*
152     * ----- org.nuxeo.ecm.core.model.Repository -----
153     */
154
155    @Override
156    public String getName() {
157        return name;
158    }
159
160    @Override
161    public org.nuxeo.ecm.core.model.Session getSession() {
162        return new SQLSession(getConnection(), this);
163    }
164
165    @Override
166    public void shutdown() {
167        try {
168            NuxeoContainer.disposeConnectionManager(connectionManager);
169        } catch (RuntimeException e) {
170            LogFactory.getLog(ConnectionFactoryImpl.class).warn("cannot dispose connection manager of " + name);
171        }
172        try {
173            managedConnectionFactory.shutdown();
174        } catch (NuxeoException e) {
175            LogFactory.getLog(ConnectionFactoryImpl.class).warn("cannot shutdown connection factory  " + name);
176        }
177    }
178
179    @Override
180    public FulltextConfiguration getFulltextConfiguration() {
181        return managedConnectionFactory.getFulltextConfiguration();
182    }
183
184    /*
185     * ----- org.nuxeo.ecm.core.model.RepositoryManagement -----
186     */
187
188    @Override
189    public int getActiveSessionsCount() {
190        return managedConnectionFactory.getActiveSessionsCount();
191    }
192
193    @Override
194    public long getCacheSize() {
195        return managedConnectionFactory.getCacheSize();
196    }
197
198    @Override
199    public long getCachePristineSize() {
200        return managedConnectionFactory.getCachePristineSize();
201    }
202
203    @Override
204    public long getCacheSelectionSize() {
205        return managedConnectionFactory.getCacheSelectionSize();
206    }
207
208    @Override
209    public int clearCaches() {
210        return managedConnectionFactory.clearCaches();
211    }
212
213    @Override
214    public void processClusterInvalidationsNext() {
215        managedConnectionFactory.processClusterInvalidationsNext();
216    }
217
218    @Override
219    public void markReferencedBinaries() {
220        managedConnectionFactory.markReferencedBinaries();
221    }
222
223    @Override
224    public int cleanupDeletedDocuments(int max, Calendar beforeTime) {
225        return managedConnectionFactory.cleanupDeletedDocuments(max, beforeTime);
226    }
227
228}