/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: DbQueryManagerFactory.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.database; import com.uwyn.rife.database.Datasource; import com.uwyn.rife.database.exceptions.UnsupportedJdbcDriverException; import com.uwyn.rife.tools.StringUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * This class allows for {@link DbQueryManager}s to be created more * dynamically and with more features than by direct instantiation. * <p>By using the <code>DbQueryManagerFactory</code>, * <code>DbQueryManager</code> child classes can have custom methods that are * implemented by different "drivers", based on the database software behind * the {@link Datasource}. Database "drivers" are looked up through the * manager's classpath according to the package name and the encoded class * name of the JDBC driver (dots are replaced by underscores). The default, or * "generic" driver, must be created under this package and will be used when * no specific driver can be found for a particular <code>Datasource</code>. * All the created DbQueryManagers are cached in the provided cache and are * re-used on successive calls rather than being re-instantiated. * * @author JR Boyens (jboyens[remove] at uwyn dot com) * @author Geert Bevin (gbevin[remove] at uwyn dot com) * @version $Revision: 3918 $ * @since 1.0 */ public abstract class DbQueryManagerFactory { private final static String GENERIC_DRIVER = "generic"; /** * Get a <code>DbQueryManager</code> instance. * * @param managerPackageName the package name that corresponds to the * location of the manager * @param cache the cache to be used to cache the * <code>DbQueryManager</code>s * @param datasource the datasource to instantiate the * <code>DbQueryManager</code> for * @return the created <code>DbQueryManager</code> instance * @since 1.0 */ protected static DbQueryManager getInstance(String managerPackageName, DbQueryManagerCache cache, Datasource datasource) { return getInstance(managerPackageName, cache, datasource, ""); } /** * Get a <code>DbQueryManager</code> instance. * * @param managerPackageName the package name that corresponds to the * location of the manager * @param cache the cache to be used to cache the * <code>DbQueryManager</code>s * @param datasource the datasource to instantiate the * <code>DbQueryManager</code> for * @param identifier the identifier to be used to uniquely identify * this <code>DbQueryManager</code> * @return the created <code>DbQueryManager</code> instance * @return the created <code>DbQueryManager</code> instance * @since 1.0 */ protected static DbQueryManager getInstance(String managerPackageName, DbQueryManagerCache cache, Datasource datasource, String identifier) { if (null == managerPackageName) throw new IllegalArgumentException("managerPackageName can't be null."); if (0 == managerPackageName.length()) throw new IllegalArgumentException("managerPackageName can't be empty."); if (null == cache) throw new IllegalArgumentException("cache can't be null."); if (null == datasource) throw new IllegalArgumentException("datasource can't be null."); if (null == identifier) throw new IllegalArgumentException("identifier can't be null."); DbQueryManager dbquery_manager = null; synchronized (cache) { dbquery_manager = cache.get(datasource, identifier); if (dbquery_manager != null) { return dbquery_manager; } // construct an uniform package name StringBuilder package_name = new StringBuilder(managerPackageName); if (!managerPackageName.endsWith(".")) { package_name.append("."); } // construct the specialized driver class name StringBuilder specialized_name = new StringBuilder(package_name.toString()); String driver = datasource.getAliasedDriver(); specialized_name.append(StringUtils.encodeClassname(driver)); try { try { Class<DbQueryManager> specialized_class = (Class<DbQueryManager>)Class.forName(specialized_name.toString()); Constructor<DbQueryManager> specialized_constructor = specialized_class.getConstructor(new Class[] {Datasource.class}); dbquery_manager = specialized_constructor.newInstance(new Object[] {datasource}); } catch (ClassNotFoundException e) { // could not find a specialized class, try to get a generic driver try { // construct the generic driver class name StringBuilder generic_name = new StringBuilder(package_name.toString()); generic_name.append(GENERIC_DRIVER); Class<DbQueryManager> generic_class = (Class<DbQueryManager>)Class.forName(generic_name.toString()); Constructor<DbQueryManager> generic_constructor = generic_class.getConstructor(new Class[] {Datasource.class}); dbquery_manager = generic_constructor.newInstance(new Object[] {datasource}); } catch (ClassNotFoundException e2) { throw new UnsupportedJdbcDriverException(driver, e); } } } catch (InstantiationException e) { throw new UnsupportedJdbcDriverException(driver, e); } catch (IllegalAccessException e) { throw new UnsupportedJdbcDriverException(driver, e); } catch (NoSuchMethodException e) { throw new UnsupportedJdbcDriverException(driver, e); } catch (SecurityException e) { throw new UnsupportedJdbcDriverException(driver, e); } catch (InvocationTargetException e) { if (e.getTargetException() != null) { throw new RuntimeException(e.getTargetException()); } else { throw new UnsupportedJdbcDriverException(driver, e); } } cache.put(datasource, identifier, dbquery_manager); } assert null != dbquery_manager; assert datasource == dbquery_manager.getDatasource(); return dbquery_manager; } }