001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: DbQueryManagerFactory.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.database;
009:
010: import com.uwyn.rife.database.Datasource;
011: import com.uwyn.rife.database.exceptions.UnsupportedJdbcDriverException;
012: import com.uwyn.rife.tools.StringUtils;
013: import java.lang.reflect.Constructor;
014: import java.lang.reflect.InvocationTargetException;
015:
016: /**
017: * This class allows for {@link DbQueryManager}s to be created more
018: * dynamically and with more features than by direct instantiation.
019: * <p>By using the <code>DbQueryManagerFactory</code>,
020: * <code>DbQueryManager</code> child classes can have custom methods that are
021: * implemented by different "drivers", based on the database software behind
022: * the {@link Datasource}. Database "drivers" are looked up through the
023: * manager's classpath according to the package name and the encoded class
024: * name of the JDBC driver (dots are replaced by underscores). The default, or
025: * "generic" driver, must be created under this package and will be used when
026: * no specific driver can be found for a particular <code>Datasource</code>.
027: * All the created DbQueryManagers are cached in the provided cache and are
028: * re-used on successive calls rather than being re-instantiated.
029: *
030: * @author JR Boyens (jboyens[remove] at uwyn dot com)
031: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
032: * @version $Revision: 3634 $
033: * @since 1.0
034: */
035: public abstract class DbQueryManagerFactory {
036: private final static String GENERIC_DRIVER = "generic";
037:
038: /**
039: * Get a <code>DbQueryManager</code> instance.
040: *
041: * @param managerPackageName the package name that corresponds to the
042: * location of the manager
043: * @param cache the cache to be used to cache the
044: * <code>DbQueryManager</code>s
045: * @param datasource the datasource to instantiate the
046: * <code>DbQueryManager</code> for
047: * @return the created <code>DbQueryManager</code> instance
048: * @since 1.0
049: */
050: protected static DbQueryManager getInstance(
051: String managerPackageName, DbQueryManagerCache cache,
052: Datasource datasource) {
053: return getInstance(managerPackageName, cache, datasource, "");
054: }
055:
056: /**
057: * Get a <code>DbQueryManager</code> instance.
058: *
059: * @param managerPackageName the package name that corresponds to the
060: * location of the manager
061: * @param cache the cache to be used to cache the
062: * <code>DbQueryManager</code>s
063: * @param datasource the datasource to instantiate the
064: * <code>DbQueryManager</code> for
065: * @param identifier the identifier to be used to uniquely identify
066: * this <code>DbQueryManager</code>
067: * @return the created <code>DbQueryManager</code> instance
068: * @return the created <code>DbQueryManager</code> instance
069: * @since 1.0
070: */
071: protected static DbQueryManager getInstance(
072: String managerPackageName, DbQueryManagerCache cache,
073: Datasource datasource, String identifier) {
074: if (null == managerPackageName)
075: throw new IllegalArgumentException(
076: "managerPackageName can't be null.");
077: if (0 == managerPackageName.length())
078: throw new IllegalArgumentException(
079: "managerPackageName can't be empty.");
080: if (null == cache)
081: throw new IllegalArgumentException("cache can't be null.");
082: if (null == datasource)
083: throw new IllegalArgumentException(
084: "datasource can't be null.");
085: if (null == identifier)
086: throw new IllegalArgumentException(
087: "identifier can't be null.");
088:
089: DbQueryManager dbquery_manager = null;
090:
091: synchronized (cache) {
092: dbquery_manager = cache.get(datasource, identifier);
093: if (dbquery_manager != null) {
094: return dbquery_manager;
095: }
096:
097: // construct an uniform package name
098: StringBuilder package_name = new StringBuilder(
099: managerPackageName);
100: if (!managerPackageName.endsWith(".")) {
101: package_name.append(".");
102: }
103:
104: // construct the specialized driver class name
105: StringBuilder specialized_name = new StringBuilder(
106: package_name.toString());
107:
108: String driver = datasource.getAliasedDriver();
109: specialized_name
110: .append(StringUtils.encodeClassname(driver));
111:
112: try {
113: try {
114: Class<DbQueryManager> specialized_class = (Class<DbQueryManager>) Class
115: .forName(specialized_name.toString());
116: Constructor<DbQueryManager> specialized_constructor = specialized_class
117: .getConstructor(new Class[] { Datasource.class });
118:
119: dbquery_manager = specialized_constructor
120: .newInstance(new Object[] { datasource });
121: } catch (ClassNotFoundException e) {
122: // could not find a specialized class, try to get a generic driver
123: try {
124: // construct the generic driver class name
125: StringBuilder generic_name = new StringBuilder(
126: package_name.toString());
127: generic_name.append(GENERIC_DRIVER);
128:
129: Class<DbQueryManager> generic_class = (Class<DbQueryManager>) Class
130: .forName(generic_name.toString());
131: Constructor<DbQueryManager> generic_constructor = generic_class
132: .getConstructor(new Class[] { Datasource.class });
133:
134: dbquery_manager = generic_constructor
135: .newInstance(new Object[] { datasource });
136: } catch (ClassNotFoundException e2) {
137: throw new UnsupportedJdbcDriverException(
138: driver, e);
139: }
140: }
141: } catch (InstantiationException e) {
142: throw new UnsupportedJdbcDriverException(driver, e);
143: } catch (IllegalAccessException e) {
144: throw new UnsupportedJdbcDriverException(driver, e);
145: } catch (NoSuchMethodException e) {
146: throw new UnsupportedJdbcDriverException(driver, e);
147: } catch (SecurityException e) {
148: throw new UnsupportedJdbcDriverException(driver, e);
149: } catch (InvocationTargetException e) {
150: if (e.getTargetException() != null) {
151: throw new RuntimeException(e.getTargetException());
152: } else {
153: throw new UnsupportedJdbcDriverException(driver, e);
154: }
155: }
156:
157: cache.put(datasource, identifier, dbquery_manager);
158: }
159:
160: assert null != dbquery_manager;
161: assert datasource == dbquery_manager.getDatasource();
162:
163: return dbquery_manager;
164: }
165: }
|