| /* $Id$ */ |
| |
| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.manifoldcf.jdbc; |
| |
| import org.apache.manifoldcf.core.interfaces.*; |
| import org.apache.manifoldcf.core.jdbcpool.*; |
| import org.apache.manifoldcf.agents.interfaces.*; |
| import org.apache.manifoldcf.crawler.system.Logging; |
| import org.apache.manifoldcf.crawler.system.ManifoldCF; |
| |
| import java.util.*; |
| import java.sql.*; |
| import javax.naming.*; |
| import javax.sql.*; |
| import java.util.*; |
| |
| /** This class creates a connection |
| */ |
| public class JDBCConnectionFactory |
| { |
| public static final String _rcsid = "@(#)$Id$"; |
| |
| private static Map<String,String> driverMap; |
| |
| private static ConnectionPoolManager _pool = null; |
| |
| static |
| { |
| driverMap = new HashMap<String,String>(); |
| driverMap.put("oracle:thin:@", "oracle.jdbc.OracleDriver"); |
| driverMap.put("postgresql://", "org.postgresql.Driver"); |
| driverMap.put("jtds:sqlserver://", "net.sourceforge.jtds.jdbc.Driver"); |
| driverMap.put("jtds:sybase://", "net.sourceforge.jtds.jdbc.Driver"); |
| driverMap.put("mysql://", "com.mysql.jdbc.Driver"); |
| driverMap.put("mariadb://", "org.mariadb.jdbc.Driver"); |
| driverMap.put("xbib:csv:", "org.xbib.jdbc.csv.CsvDriver"); |
| try |
| { |
| _pool = new ConnectionPoolManager(120,false); |
| } |
| catch (Exception e) |
| { |
| System.err.println("Can't set up pool"); |
| e.printStackTrace(System.err); |
| } |
| } |
| |
| private JDBCConnectionFactory() |
| { |
| } |
| |
| /** Convert various connection parameters to a JDBC connection string, used in conjunction with the |
| * provider name. |
| */ |
| public static String getJDBCDriverString(String providerName, String host, String database, String rawDriverString) |
| { |
| if (rawDriverString != null && rawDriverString.length() > 0) |
| return rawDriverString; |
| |
| if (database.length() == 0) |
| database = "_root_"; |
| |
| String instanceName = null; |
| // Special for MSSQL: Allow database spec to contain an instance name too, in form: |
| // <instance>/<database> |
| if (providerName.startsWith("jtds:")) |
| { |
| int slashIndex = database.indexOf("/"); |
| if (slashIndex != -1) |
| { |
| instanceName = database.substring(0,slashIndex); |
| database = database.substring(slashIndex+1); |
| } |
| } |
| |
| return host + "/" + database + ((instanceName==null)?"":";instance="+instanceName); |
| } |
| |
| public static WrappedConnection getConnection(String providerName, String jdbcDriverString, String userName, String password) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| String driverClassName = driverMap.get(providerName); |
| if (driverClassName == null) |
| throw new ManifoldCFException("Unrecognized jdbc provider: '"+providerName+"'"); |
| |
| String dburl = "jdbc:" + providerName + jdbcDriverString; |
| if (Logging.connectors != null && Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JDBC: The connect string is '"+dburl+"'"); |
| try |
| { |
| // Hope for a connection now |
| if (_pool != null) |
| { |
| // Build a unique string to identify the pool. This has to include |
| // the database and host at a minimum. |
| |
| // Provider is part of the pool key, so that the pools can distinguish between different databases |
| String poolKey = providerName + "/" + jdbcDriverString; |
| |
| // Better include the credentials on the pool key, or we won't be able to change those and have it build new connections |
| // The password value is SHA-1 hashed, because the pool driver reports the password in many exceptions and we don't want it |
| // to be displayed. |
| poolKey += "/" + userName + "/" + ManifoldCF.hash(password); |
| |
| ConnectionPool cp; |
| synchronized (_pool) |
| { |
| cp = _pool.getPool(poolKey); |
| if (cp == null) |
| { |
| // Register the driver here |
| Class.forName(driverClassName); |
| //System.out.println("Class name '"+driverClassName+"'; URL = '"+dburl+"'"); |
| cp =_pool.addAlias(poolKey, driverClassName, dburl, |
| userName, password, 30, 300000L); |
| } |
| } |
| return cp.getConnection(); |
| } |
| else |
| throw new ManifoldCFException("Can't get connection since pool driver did not initialize properly"); |
| } |
| catch (InterruptedException e) |
| { |
| throw new ManifoldCFException(e.getMessage(),ManifoldCFException.INTERRUPTED); |
| } |
| catch (java.sql.SQLException e) |
| { |
| e.printStackTrace(); |
| // Unfortunately, the connection pool manager manages to eat all actual connection setup errors. This makes it very hard to figure anything out |
| // when something goes wrong. So, we try again, going directly this time as a means of getting decent error feedback. |
| try |
| { |
| if (userName != null && userName.length() > 0) |
| { |
| DriverManager.getConnection(dburl, userName, password).close(); |
| } |
| else |
| { |
| DriverManager.getConnection(dburl).close(); |
| } |
| } |
| catch (java.sql.SQLException e2) |
| { |
| throw new ManifoldCFException("Error getting connection: "+e2.getMessage(),e2,ManifoldCFException.SETUP_ERROR); |
| } |
| // By definition, this must be a service interruption, because the direct route in setting up the connection succeeded. |
| long currentTime = System.currentTimeMillis(); |
| throw new ServiceInterruption("Error getting connection: "+e.getMessage(),e,currentTime + 300000L,currentTime + 6 * 60 * 60000L,-1,true); |
| } |
| catch (java.lang.ClassNotFoundException e) |
| { |
| throw new ManifoldCFException("Driver class not found: "+e.getMessage(),e,ManifoldCFException.SETUP_ERROR); |
| } |
| catch (java.lang.InstantiationException e) |
| { |
| throw new ManifoldCFException("Driver class not instantiable: "+e.getMessage(),e,ManifoldCFException.SETUP_ERROR); |
| } |
| catch (java.lang.IllegalAccessException e) |
| { |
| throw new ManifoldCFException("Driver class not accessible: "+e.getMessage(),e,ManifoldCFException.SETUP_ERROR); |
| } |
| } |
| |
| public static void releaseConnection(WrappedConnection c) |
| { |
| c.release(); |
| } |
| |
| } |
| |