Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » schema » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.jdbc.schema;
   20   
   21   import java.security.AccessController;
   22   import java.sql.Connection;
   23   import java.sql.Driver;
   24   import java.sql.SQLException;
   25   import java.util.ArrayList;
   26   import java.util.Arrays;
   27   import java.util.Iterator;
   28   import java.util.List;
   29   import javax.sql.DataSource;
   30   
   31   import org.apache.commons.lang.StringUtils;
   32   import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
   33   import org.apache.openjpa.jdbc.sql.DBDictionary;
   34   import org.apache.openjpa.lib.conf.Configurations;
   35   import org.apache.openjpa.lib.jdbc.ConfiguringConnectionDecorator;
   36   import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
   37   import org.apache.openjpa.lib.jdbc.DecoratingDataSource;
   38   import org.apache.openjpa.lib.jdbc.DelegatingDataSource;
   39   import org.apache.openjpa.lib.jdbc.JDBCEventConnectionDecorator;
   40   import org.apache.openjpa.lib.jdbc.JDBCListener;
   41   import org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator;
   42   import org.apache.openjpa.lib.log.Log;
   43   import org.apache.openjpa.lib.util.J2DoPrivHelper;
   44   import org.apache.openjpa.lib.util.Localizer;
   45   import org.apache.openjpa.lib.util.Options;
   46   import org.apache.openjpa.util.ImplHelper;
   47   import org.apache.openjpa.util.OpenJPAException;
   48   import org.apache.openjpa.util.StoreException;
   49   import org.apache.openjpa.util.UserException;
   50   
   51   /**
   52    * Factory for {@link DataSource} objects. The factory uses the supplied
   53    * configuration to obtain a 3rd-party datasource or to create one, and
   54    * to setup prepared statement caching.
   55    *
   56    * @author Abe White
   57    * @nojavadoc
   58    */
   59   public class DataSourceFactory {
   60   
   61       private static final Localizer _loc = Localizer.forPackage
   62           (DataSourceFactory.class);
   63   
   64       /**
   65        * Create a datasource using the given configuration.
   66        */
   67       public static DataSource newDataSource(JDBCConfiguration conf,
   68           boolean factory2) {
   69           String driver = (factory2) ? conf.getConnection2DriverName()
   70               : conf.getConnectionDriverName();
   71           if (StringUtils.isEmpty(driver))
   72               throw new UserException(_loc.get("no-driver", driver)).
   73                   setFatal(true);
   74   
   75           ClassLoader loader = conf.getClassResolverInstance().
   76               getClassLoader(DataSourceFactory.class, null);
   77           String props = (factory2) ? conf.getConnection2Properties()
   78               : conf.getConnectionProperties();
   79           try {
   80               Class driverClass;
   81               try {
   82                   driverClass = Class.forName(driver, true, loader);
   83               } catch (ClassNotFoundException cnfe) {
   84                   // try with the core class loader
   85                   driverClass = Class.forName(driver);
   86               }
   87   
   88               if (Driver.class.isAssignableFrom(driverClass)) {
   89                   DriverDataSource ds = conf.newDriverDataSourceInstance();
   90                   ds.setClassLoader(loader);
   91                   ds.setConnectionDriverName(driver);
   92                   ds.setConnectionProperties(Configurations.
   93                       parseProperties(props));
   94   
   95                   if (!factory2) {
   96                       ds.setConnectionFactoryProperties(Configurations.
   97                           parseProperties(conf.getConnectionFactoryProperties()));
   98                       ds.setConnectionURL(conf.getConnectionURL());
   99                       ds.setConnectionUserName(conf.getConnectionUserName());
  100                       ds.setConnectionPassword(conf.getConnectionPassword());
  101                   } else {
  102                       ds.setConnectionFactoryProperties
  103                           (Configurations.parseProperties(conf.
  104                           getConnectionFactory2Properties()));
  105                       ds.setConnectionURL(conf.getConnection2URL());
  106                       ds.setConnectionUserName(conf.getConnection2UserName());
  107                       ds.setConnectionPassword(conf.getConnection2Password());
  108                   }
  109                   return ds;
  110               }
  111   
  112               // see if their driver name is actually a data source
  113               if (DataSource.class.isAssignableFrom(driverClass)) {
  114                   return (DataSource) Configurations.newInstance(driver,
  115                       conf, props, (ClassLoader) AccessController.doPrivileged(
  116                           J2DoPrivHelper.getClassLoaderAction(
  117                               DataSource.class))); 
  118               }
  119           }
  120           catch (OpenJPAException ke) {
  121               throw ke;
  122           } catch (Exception e) {
  123               throw new StoreException(e).setFatal(true);
  124           }
  125   
  126           // not a driver or a data source; die
  127           throw new UserException(_loc.get("bad-driver", driver)).setFatal(true);
  128       }
  129   
  130       /**
  131        * Install listeners and base decorators.
  132        */
  133       public static DecoratingDataSource decorateDataSource(DataSource ds,
  134           JDBCConfiguration conf, boolean factory2) {
  135           Options opts = Configurations.parseProperties((factory2)
  136               ? conf.getConnectionFactory2Properties()
  137               : conf.getConnectionFactoryProperties());
  138           Log jdbcLog = conf.getLog(JDBCConfiguration.LOG_JDBC);
  139           Log sqlLog = conf.getLog(JDBCConfiguration.LOG_SQL);
  140   
  141           DecoratingDataSource dds = new DecoratingDataSource(ds);
  142           try {
  143               // add user-defined decorators
  144               List decorators = new ArrayList();
  145               decorators.addAll(Arrays.asList(conf.
  146                   getConnectionDecoratorInstances()));
  147   
  148               // add jdbc events decorator
  149               JDBCEventConnectionDecorator ecd =
  150                   new JDBCEventConnectionDecorator();
  151               Configurations.configureInstance(ecd, conf, opts);
  152               JDBCListener[] listeners = conf.getJDBCListenerInstances();
  153               for (int i = 0; i < listeners.length; i++)
  154                   ecd.addListener(listeners[i]);
  155               decorators.add(ecd);
  156   
  157               // ask the DriverDataSource to provide any additional decorators
  158               if (ds instanceof DriverDataSource) {
  159                   List decs = ((DriverDataSource) ds).
  160                       createConnectionDecorators();
  161                   if (decs != null)
  162                       decorators.addAll(decs);
  163               }
  164   
  165               // logging decorator
  166               LoggingConnectionDecorator lcd =
  167                   new LoggingConnectionDecorator();
  168               Configurations.configureInstance(lcd, conf, opts);
  169               lcd.getLogs().setJDBCLog(jdbcLog);
  170               lcd.getLogs().setSQLLog(sqlLog);
  171               decorators.add(lcd);
  172   
  173               dds.addDecorators(decorators);
  174               return dds;
  175           } catch (OpenJPAException ke) {
  176               throw ke;
  177           } catch (Exception e) {
  178               throw new StoreException(e).setFatal(true);
  179           }
  180       }
  181   
  182       /**
  183        * Install things deferred until the DBDictionary instance is available.
  184        *
  185        * @author Steve Kim
  186        */
  187       public static DecoratingDataSource installDBDictionary(DBDictionary dict,
  188           DecoratingDataSource ds, final JDBCConfiguration conf,
  189           boolean factory2) {
  190           DataSource inner = ds.getInnermostDelegate();
  191           if (inner instanceof DriverDataSource)
  192               ((DriverDataSource) inner).initDBDictionary(dict);
  193           Connection conn = null;
  194   
  195           try {
  196               // add the dictionary as a warning handler on the logging
  197               // decorator
  198               ConnectionDecorator cd;
  199               for (Iterator itr = ds.getDecorators().iterator(); itr.hasNext();) {
  200                   cd = (ConnectionDecorator) itr.next();
  201                   if (cd instanceof LoggingConnectionDecorator)
  202                       ((LoggingConnectionDecorator) cd).setWarningHandler(dict);
  203               }
  204   
  205               // misc configuration connection decorator (statement timeouts,
  206               // transaction isolation, etc)
  207               ConfiguringConnectionDecorator ccd =
  208                   new ConfiguringConnectionDecorator();
  209               ccd.setTransactionIsolation(conf.getTransactionIsolationConstant());
  210               if (factory2 || !conf.isConnectionFactoryModeManaged()) {
  211                   if (!dict.supportsMultipleNontransactionalResultSets)
  212                       ccd.setAutoCommit(Boolean.FALSE);
  213                   else
  214                       ccd.setAutoCommit(Boolean.TRUE);
  215               }
  216               Options opts = Configurations.parseProperties((factory2)
  217                   ? conf.getConnectionFactory2Properties()
  218                   : conf.getConnectionFactoryProperties());
  219               Configurations.configureInstance(ccd, conf, opts);
  220               ds.addDecorator(ccd);
  221   
  222               // allow the dbdictionary to decorate the connection further
  223               ds.addDecorator(dict);
  224               
  225               // ensure dbdictionary to process connectedConfiguration()
  226               if (!factory2)
  227                   conn = ds.getConnection(conf.getConnectionUserName(), conf
  228                           .getConnectionPassword());
  229               else
  230                   conn = ds.getConnection(conf.getConnection2UserName(), conf
  231                           .getConnection2Password());
  232   
  233               return ds;
  234           } catch (Exception e) {
  235               throw new StoreException(e).setFatal(true);
  236           } finally {
  237               if (conn != null)
  238                   try {
  239                       conn.close();
  240                   } catch (SQLException se) {
  241                       // ignore any exception since the connection is not going
  242                       // to be used anyway
  243                   }
  244           }
  245       }
  246   
  247       /**
  248        * Return a data source with the given user name and password
  249        * pre-configured as the defaults when {@link DataSource#getConnection}
  250        * is called.
  251        */
  252       public static DataSource defaultsDataSource(DataSource ds,
  253           String user, String pass) {
  254           if (user == null && pass == null)
  255               return ds;
  256           // also check if they are both blank strings
  257           if ("".equals(user) && "".equals(pass))
  258               return ds;
  259           return new DefaultsDataSource(ds, user, pass);
  260       }
  261   
  262       /**
  263        * Close the given data source.
  264        */
  265       public static void closeDataSource(DataSource ds) {
  266           if (ds instanceof DelegatingDataSource)
  267               ds = ((DelegatingDataSource) ds).getInnermostDelegate();
  268           ImplHelper.close(ds);
  269       }
  270   
  271       /**
  272        * A data source with pre-configured default user name and password.
  273        */
  274       private static class DefaultsDataSource
  275           extends DelegatingDataSource {
  276   
  277           private final String _user;
  278           private final String _pass;
  279   
  280           public DefaultsDataSource(DataSource ds, String user, String pass) {
  281               super(ds);
  282               _user = user;
  283               _pass = pass;
  284           }
  285   
  286           public Connection getConnection()
  287               throws SQLException {
  288               return super.getConnection(_user, _pass);
  289           }
  290   
  291           public Connection getConnection(String user, String pass)
  292               throws SQLException {
  293               return super.getConnection(user, pass);
  294           }
  295       }
  296   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » schema » [javadoc | source]