KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mapper > RepositoryDataSource


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.mapper;
24
25 import java.io.PrintWriter JavaDoc;
26 import java.sql.SQLException JavaDoc;
27 import java.util.HashMap JavaDoc;
28
29 import javax.sql.DataSource JavaDoc;
30
31 import org.xquark.mapper.dbms.AbstractConnection;
32 import org.xquark.mapper.dbms.AbstractConnectionFactory;
33 import org.xquark.mapper.dbms.RepositoryConnectionImpl;
34 import org.xquark.mapper.metadata.Repository;
35 import org.xquark.mapper.util.CounterMap;
36 import org.xquark.mapper.util.DestructionToken;
37 import org.xquark.xml.xdbc.XMLConnection;
38 import org.xquark.xml.xdbc.XMLDBCException;
39 import org.xquark.xml.xdbc.XMLDataSource;
40
41 /**
42  * XMLDBC data source implementation
43  */

44 public final class RepositoryDataSource implements XMLDataSource
45 {
46     private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
47     private static final String JavaDoc RCSName = "$Name: $";
48     
49     private static final String JavaDoc ORACLE_URL_PREFIX = "jdbc:oracle";
50     private static final String JavaDoc TIMESTEN_URL_PREFIX = "jdbc:timesten";
51     private static final String JavaDoc SYBASE_URL_PREFIX = "jdbc:sybase";
52     private static final String JavaDoc SQLSERVER_URL_PREFIX = "jdbc:microsoft:sqlserver";
53     
54     private static final String JavaDoc ORACLE_DRIVER_CLASS = "oracle.jdbc.driver.OracleDriver";
55     private static final String JavaDoc TIMESTEN_DRIVER_CLASS = "com.timesten.jdbc.TimesTenDriver";
56     private static final String JavaDoc SYBASE_DRIVER_CLASS = "com.sybase.jdbc2.jdbc.SybDriver";
57     private static final String JavaDoc SQLSERVER_DRIVER_CLASS = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
58
59     private static final String JavaDoc DATA_SOURCE_FAKE_NAME = "DS";
60     
61     private CounterMap repositories = new CounterMap();
62     private HashMap JavaDoc standByRepositories = new HashMap JavaDoc();
63     
64     private AbstractConnectionFactory connectionFactory;
65     private DataSource JavaDoc JDBCDs;
66     
67     private PrintWriter JavaDoc logger;
68     private int logTimeout;
69     
70     /** Constructor to use for later calls to getConnection(user, password)
71      * methods.
72      * @param url a valid JDBC url to a relational database.
73      * @throws XMLDBCException if URL provided is not reachable.
74      */

75     public RepositoryDataSource(String JavaDoc url)
76     throws XMLDBCException
77     {
78         acceptsJDBCURL(url);
79         connectionFactory = new AbstractConnectionFactory(url);
80     }
81     
82     /** Constructor to use for later calls to getConnection()
83      * methods. This method allows using JDBC DataSources using a pool
84      * of connections.
85      * @param ds A JDBC {@link javax.sql.DataSource} object.
86      */

87     public RepositoryDataSource(DataSource JavaDoc ds)
88     {
89         JDBCDs = ds;
90     }
91     
92     private boolean acceptsJDBCURL(String JavaDoc url) throws XMLDBCException
93     {
94         try {
95             // automatic load for know drivers
96
if (url.startsWith(ORACLE_URL_PREFIX))
97                 Class.forName(ORACLE_DRIVER_CLASS);
98             else if (url.startsWith(TIMESTEN_URL_PREFIX))
99                 Class.forName(TIMESTEN_DRIVER_CLASS);
100             else if (url.startsWith(SYBASE_URL_PREFIX))
101                 Class.forName(SYBASE_DRIVER_CLASS);
102             else if (url.startsWith(SQLSERVER_URL_PREFIX))
103                 Class.forName(SQLSERVER_DRIVER_CLASS);
104             // else driver is supposed to be loaded
105
}
106         catch (Exception JavaDoc e)
107         {
108             throw new XMLDBCException("JDBC driver could not be found. Check your classpath or load it yourself if it is not supported.");
109         }
110              
111         return true;
112     }
113     
114     /** Retrieves the log writer currently used by the XDataSource object to print messages.
115      * @return the java.io.PrintWriter object used to log data source messages, or null if none is defined
116      */

117     public java.io.PrintWriter JavaDoc getLogWriter()
118     {
119         return logger;
120     }
121     
122     /** Sets the logging/tracing java.io.PrintWriter object that is used by the XDataSource object.
123      * @param writer the new logging/tracing java.io.PrintWriter object, or null to disable logging and tracing
124      */

125     public void setLogWriter(PrintWriter JavaDoc writer)
126     {
127         logger = writer;
128     }
129     
130     /** Sets the maximum time in seconds that the object will wait when attempting to log in to a data source. Setting the timeout to 0 will disable it.
131      * @param seconds the login time limit in seconds
132      */

133     public void setLoginTimeout(int seconds)
134     {
135         logTimeout = seconds;
136     }
137     
138     /** Gets the maximum time in seconds that the object can wait when attempting to log in to a data source
139      * @return the data source login timeout in seconds, 0 if no timeout is defined
140      */

141     public int getLoginTimeout()
142     {
143         return logTimeout;
144     }
145     
146     /** Attempts to establish a connection with the Repository specified by
147      * the URL given to the constructor and the user parameter.
148      * @param user the user owning the repository
149      * @param password the user's password
150      * @throws XMLDBCException If a data source access error occurs
151      * @return an XMLConnection object that represents a connection to the
152      * repository data source
153      */

154     public XMLConnection getConnection(String JavaDoc user, String JavaDoc password) throws XMLDBCException
155     {
156         return getRepositoryConnection(user, password);
157     }
158     
159     /** The same as {@link #getConnection(String,String)} method but
160      * returning a RepositoryConnection object, giving access to the
161      * Repository extended API.
162      * @param user the user owning the repository
163      * @param password the user's password
164      * @throws XMLDBCException If a data source access error occurs
165      * @return an RepositoryConnection object that represents a connection to
166      * the repository.
167      */

168     public RepositoryConnection getRepositoryConnection(String JavaDoc user, String JavaDoc password)
169     throws XMLDBCException
170     {
171         String JavaDoc key = user.toUpperCase();
172
173         Repository rep = (Repository)repositories.checkOut(key);
174         
175         try {
176             if (rep == null)
177             {
178                 // look in the "stand bys"
179
rep = (Repository)standByRepositories.get(key);
180                 if (rep == null)
181                     rep = new Repository(getAbstractConnection(user, password));
182                 else
183                     rep.restoreConnection(getAbstractConnection(user, password));
184                 repositories.put(key, rep);
185             }
186             
187             return new RepositoryConnectionImpl(
188                                             rep,
189                                             getAbstractConnection(user, password),
190                                             new ConnectionDestructor()
191                                             );
192         }
193         catch (SQLException JavaDoc e) {
194             throw new RepositoryException(RepositoryException.DB_ERROR,
195             "JDBC error while creating a RepositoryConnection.", e);
196         }
197
198     }
199     
200     /** Attempts to establish a connection with a repository using the JDBC data
201      * source specified in the constructor.
202      * @throws XMLDBCException If a data source access error occurs
203      * @return an XMLConnection object that represents a connection to the
204      * repository data source
205      */

206     public XMLConnection getConnection() throws XMLDBCException
207     {
208         return getRepositoryConnection();
209     }
210     
211     /** The same as {@link #getConnection()} method but returning a
212      * RepositoryConnection object, giving access to the Repository extended API.
213      * @throws XMLDBCException If a data source access error occurs
214      * @return an RepositoryConnection object that represents a connection to
215      * the repository.
216      */

217     public RepositoryConnection getRepositoryConnection() throws XMLDBCException
218     {
219         Repository rep = (Repository)repositories.checkOut(DATA_SOURCE_FAKE_NAME);
220         
221         try
222         {
223             if (rep == null)
224             {
225                 // look in the "stand bys"
226
rep = (Repository)standByRepositories.get(DATA_SOURCE_FAKE_NAME);
227                 if (rep == null)
228                     rep = new Repository(getAbstractConnection());
229                 else
230                     rep.restoreConnection(getAbstractConnection());
231                 repositories.put(DATA_SOURCE_FAKE_NAME, rep);
232             }
233             
234             return new RepositoryConnectionImpl(
235             rep,
236             getAbstractConnection(),
237             new DSConnectionDestructor()
238             );
239         }
240         catch (SQLException JavaDoc e)
241         {
242             throw new RepositoryException(RepositoryException.DB_ERROR,
243             "JDBC error while creating a RepositoryConnection.", e);
244         }
245     }
246     
247     //////////////////////////////////////////////////////////////
248
// PRIVATE
249
//////////////////////////////////////////////////////////////
250
private AbstractConnection getAbstractConnection() throws SQLException JavaDoc
251     {
252         if (JDBCDs == null)
253             return connectionFactory.getAbstractConnection();
254         else
255             return AbstractConnectionFactory.newConnection(JDBCDs.getConnection());
256     }
257     
258     private AbstractConnection getAbstractConnection(String JavaDoc user, String JavaDoc password)
259     throws SQLException JavaDoc
260     {
261         if (JDBCDs == null)
262             return connectionFactory.getAbstractConnection(user, password);
263         else
264             return AbstractConnectionFactory.newConnection(
265                                             JDBCDs.getConnection(user, password)
266                                             );
267     }
268     
269     private void releaseConnection(String JavaDoc user)
270     {
271             Repository rep = (Repository)repositories.remove(user);
272             
273             try
274             {
275                 if (rep != null)
276                 {
277                     if (rep.isAlive()) // physical repository may have been destroyed
278
{
279                         rep.withdrawConnection(); // put repository metadata in standby
280
standByRepositories.put(user, rep);
281                     }
282                     else
283                         rep.close();
284                 }
285             }
286             catch (XMLDBCException e)
287             {
288                 // ignore
289
}
290     }
291     
292     private class ConnectionDestructor implements DestructionToken
293     {
294         public void destruct(Object JavaDoc o)
295         {
296             try
297             {
298                 releaseConnection(((RepositoryConnection)o).getUserName());
299             }
300             catch (XMLDBCException e)
301             {
302                 // ignore
303
}
304         }
305     }
306     
307     private class DSConnectionDestructor implements DestructionToken
308     {
309         public void destruct(Object JavaDoc o)
310         {
311             releaseConnection(DATA_SOURCE_FAKE_NAME);
312         }
313     }
314 }
315
Popular Tags