001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.console.internaldb;
019    
020    import java.sql.Connection;
021    import java.sql.DriverManager;
022    import java.sql.SQLException;
023    import java.util.HashMap;
024    import java.util.Iterator;
025    
026    import javax.sql.DataSource;
027    
028    import org.apache.commons.logging.Log;
029    import org.apache.commons.logging.LogFactory;
030    import org.apache.geronimo.gbean.AbstractName;
031    import org.apache.geronimo.gbean.AbstractNameQuery;
032    import org.apache.geronimo.kernel.KernelRegistry;
033    import org.apache.geronimo.kernel.repository.Artifact;
034    import org.apache.geronimo.kernel.repository.Version;
035    
036    import org.apache.geronimo.derby.DerbySystemGBean;
037    
038    /**
039     * A static class to handle retreiving connections. This class is built to
040     * handle lookups to the SystemDatabase as a special case. If a connection is
041     * requested for the SystemDatabase this class gets a DataSource from an admin
042     * object registered in the geronimo kernel otherwise the DataSource is looked
043     * up via JNDI.
044     *
045     * @version $Rev: 497248 $ $Date: 2007-01-17 18:42:34 -0500 (Wed, 17 Jan 2007) $
046     */
047    public class DerbyConnectionUtil {
048    
049        private final static Log log = LogFactory.getLog(DerbyConnectionUtil.class);
050    
051            public static final String CREATE_DB_PROP = ";create=true";
052    
053        public static final String SHUTDOWN_DB_PROP = ";shutdown=true";
054    
055        private static final int RDBMS_DERBY = 1;
056    
057        private static final int RDBMS_MSSQL = 2;
058    
059        private static final String SYSTEM_DB = "SYSTEMDATABASE";
060    
061        private static final String DERBY_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
062    
063        private static final String PROTOCOL = "jdbc:derby:";
064    
065        private static final String EMPTY_PROPS = "";
066        
067        private static AbstractName SYSTEM_DATASOURCE_NAME = null;
068        
069        static {
070            try {
071                log.debug("Looking up system datasource name...");
072                
073                // look up the system data source name without using the version number
074                HashMap props = new HashMap();
075                props.put("name","SystemDatasource");
076                props.put("j2eeType","JCAManagedConnectionFactory");
077                Artifact systemDB = new Artifact("org.apache.geronimo.configs", "system-database", (Version)null, "car");
078                AbstractNameQuery query = new AbstractNameQuery(systemDB,props);
079                Iterator iter = KernelRegistry.getSingleKernel().listGBeans(query).iterator();
080                
081                if (iter.hasNext()) {
082                    SYSTEM_DATASOURCE_NAME = (AbstractName)iter.next();
083                    log.debug("Using system datasource name: " + SYSTEM_DATASOURCE_NAME);
084                }
085                else {
086                    log.warn("Failed to lookup system datasource name");
087                }
088            }
089            catch (Throwable t) {
090                //
091                // HACK: Log any errors which occur when this is loading...
092                //       the system is not logging the full detail, which it should
093                //       but for now lets show the details here
094                //
095                log.error("Failed to initialize", t);
096                throw new Error(t);
097            }
098        }
099        
100        private static String derbyHome = null;
101        
102        /**
103         * Get the Derby home directory path.
104         */
105        public static String getDerbyHome() {
106            if (derbyHome == null) {
107                try {
108                    derbyHome = (String)KernelRegistry.getSingleKernel().getAttribute(DerbySystemGBean.class, "derbyHome");
109                }
110                catch (Exception e) {
111                    throw new RuntimeException("Failed to query derbyHome", e);
112                }
113            }
114            return derbyHome;
115        }
116        
117        /**
118         * Get database connection.
119         *
120         * @param dbName
121         * @return
122         * @throws SQLException
123         */
124        private static Connection getConnection(String dbName, String properties,
125                String protocol, String driver) throws SQLException {
126            try {
127                Class.forName(driver).newInstance();
128            } catch (Exception e) {
129                    log.error("Problem loading driver class", e);
130            }
131            // If we are looking for the SystemDatabase get it from the kernel
132            // because it is not binded to our JNDI Context.
133            if (SYSTEM_DB.equalsIgnoreCase(dbName)) {
134                return getSystemDBConnection();
135            } else {
136                return DriverManager.getConnection(protocol + dbName + properties);
137            }
138        }
139    
140        /**
141         * Get a connection to derby.
142         *
143         * @param dbName
144         *            the name of the database to connect to.
145         * @param properties
146         *            the properties to pass to the connection string.
147         * @return connection
148         */
149        public static Connection getDerbyConnection(String dbName, String properties)
150                throws SQLException {
151            return getConnection(dbName, properties, PROTOCOL, DERBY_DRIVER);
152        }
153    
154        public static Connection getDerbyConnection(String dbName)
155                throws SQLException {
156            return getDerbyConnection(dbName, EMPTY_PROPS);
157        }
158    
159        /**
160         * Get a connection to the SystemDatabase.
161         *
162         * @return
163         * @throws SQLException
164         */
165        public static Connection getSystemDBConnection() throws SQLException {
166            DataSource ds = null;
167            try {
168                ds = getDataSource(SYSTEM_DB);
169                return ds.getConnection();
170            } catch (Exception e) {
171                throw new SQLException(e.getMessage());
172            }
173        }
174    
175        /**
176         * Get the datasource if dbName is == SYSTEM_DB, otherwise returns null.
177         *
178         * @param dbName
179         * @return datasource
180         */
181        public static DataSource getDataSource(String dbName) {
182            try {
183                if (SYSTEM_DATASOURCE_NAME!=null && SYSTEM_DB.equalsIgnoreCase(dbName)) {
184                    return (DataSource) KernelRegistry.getSingleKernel().invoke(
185                                    SYSTEM_DATASOURCE_NAME, "$getResource");
186                }
187            } catch (Exception e) {
188                    log.error("Problem getting datasource " + dbName, e);
189            }
190            return null;
191        }
192    
193    }