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.Set;
024
025 import javax.sql.DataSource;
026
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029 import org.apache.geronimo.console.util.KernelManagementHelper;
030 import org.apache.geronimo.console.util.ManagementHelper;
031 import org.apache.geronimo.derby.DerbySystemGBean;
032 import org.apache.geronimo.gbean.AbstractName;
033 import org.apache.geronimo.gbean.AbstractNameQuery;
034 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
035 import org.apache.geronimo.kernel.Kernel;
036 import org.apache.geronimo.kernel.KernelRegistry;
037 import org.apache.geronimo.management.JCAManagedConnectionFactory;
038 import org.apache.geronimo.management.geronimo.ResourceAdapterModule;
039
040 /**
041 * A static class to handle retreiving connections. This class is built to
042 * handle lookups to the SystemDatabase as a special case. If a connection is
043 * requested for the SystemDatabase this class gets a DataSource from an admin
044 * object registered in the geronimo kernel otherwise the DataSource is looked
045 * up via JNDI.
046 *
047 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
048 */
049 public class DerbyConnectionUtil {
050
051 private final static Log log = LogFactory.getLog(DerbyConnectionUtil.class);
052
053 public static final String CREATE_DB_PROP = ";create=true";
054
055 public static final String SHUTDOWN_DB_PROP = ";shutdown=true";
056
057 private static final int RDBMS_DERBY = 1;
058
059 private static final int RDBMS_MSSQL = 2;
060
061 private static final String SYSTEM_DB = "SYSTEMDATABASE";
062
063 private static final String DERBY_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
064
065 private static final String PROTOCOL = "jdbc:derby:";
066
067 private static final String EMPTY_PROPS = "";
068
069 private static AbstractName SYSTEM_DATASOURCE_NAME = null;
070
071 static {
072 try {
073 log.debug("Looking up system datasource name...");
074
075 // cache the name for the system data source
076 AbstractNameQuery query = new AbstractNameQuery(JCAManagedConnectionFactory.class.getName());
077 Set<AbstractName> names = KernelRegistry.getSingleKernel().listGBeans(query);
078 for (AbstractName name : names) {
079 String nameProperty = name.getNameProperty("name");
080 if ("SystemDatasource".equals(nameProperty)) {
081 SYSTEM_DATASOURCE_NAME = name;
082 log.debug("Using system datasource name: " + SYSTEM_DATASOURCE_NAME);
083 }
084 }
085
086 if (SYSTEM_DATASOURCE_NAME == null) {
087 log.warn("Failed to lookup system datasource name");
088 }
089 }
090 catch (Throwable t) {
091 //
092 // HACK: Log any errors which occur when this is loading...
093 // the system is not logging the full detail, which it should
094 // but for now lets show the details here
095 //
096 log.error("Failed to initialize", t);
097 throw new Error(t);
098 }
099 }
100
101 private static String derbyHome = null;
102
103 /**
104 * Get the Derby home directory path.
105 */
106 public static String getDerbyHome() {
107 if (derbyHome == null) {
108 try {
109 derbyHome = (String)KernelRegistry.getSingleKernel().getAttribute(DerbySystemGBean.class, "derbyHome");
110 }
111 catch (Exception e) {
112 throw new RuntimeException("Failed to query derbyHome", e);
113 }
114 }
115 return derbyHome;
116 }
117
118 /**
119 * Get database connection.
120 *
121 * @param dbName
122 * @return
123 * @throws SQLException
124 */
125 private static Connection getConnection(String dbName, String properties,
126 String protocol, String driver) throws SQLException {
127 try {
128 Class.forName(driver).newInstance();
129 } catch (Exception e) {
130 log.error("Problem loading driver class", e);
131 }
132 // If we are looking for the SystemDatabase get it from the kernel
133 // because it is not binded to our JNDI Context.
134 if (SYSTEM_DB.equalsIgnoreCase(dbName)) {
135 return getSystemDBConnection();
136 } else {
137 return DriverManager.getConnection(protocol + dbName + properties);
138 }
139 }
140
141 /**
142 * Get a connection to derby.
143 *
144 * @param dbName
145 * the name of the database to connect to.
146 * @param properties
147 * the properties to pass to the connection string.
148 * @return connection
149 */
150 public static Connection getDerbyConnection(String dbName, String properties)
151 throws SQLException {
152 return getConnection(dbName, properties, PROTOCOL, DERBY_DRIVER);
153 }
154
155 public static Connection getDerbyConnection(String dbName)
156 throws SQLException {
157 return getDerbyConnection(dbName, EMPTY_PROPS);
158 }
159
160 /**
161 * Get a connection to the SystemDatabase.
162 *
163 * @return
164 * @throws SQLException
165 */
166 public static Connection getSystemDBConnection() throws SQLException {
167 DataSource ds = null;
168 try {
169 ds = getDataSource(SYSTEM_DB);
170 return ds.getConnection();
171 } catch (Exception e) {
172 throw new SQLException(e.getMessage());
173 }
174 }
175
176 /**
177 * Get the datasource if dbName is == SYSTEM_DB, otherwise returns null.
178 *
179 * @param dbName
180 * @return datasource
181 */
182 public static DataSource getDataSource(String dbName) {
183 try {
184 if (SYSTEM_DATASOURCE_NAME!=null && SYSTEM_DB.equalsIgnoreCase(dbName)) {
185 return (DataSource) KernelRegistry.getSingleKernel().invoke(
186 SYSTEM_DATASOURCE_NAME, "$getResource");
187 }
188 } catch (Exception e) {
189 log.error("Problem getting datasource " + dbName, e);
190 }
191
192 Kernel kernel = KernelRegistry.getSingleKernel();
193 ManagementHelper helper = new KernelManagementHelper(kernel);
194 ResourceAdapterModule[] modules = helper.getOutboundRAModules(helper.getDomains()[0].getServerInstances()[0], "javax.sql.DataSource");
195 for (ResourceAdapterModule module : modules) {
196 org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory[] databases = helper.getOutboundFactories(module, "javax.sql.DataSource");
197 for (org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory db : databases) {
198 try {
199 Object databaseName = db.getConfigProperty("DatabaseName");
200 if(dbName.equalsIgnoreCase((String) databaseName)) {
201 AbstractName tempDbName = helper.getNameFor(db);
202 return (DataSource) KernelRegistry.getSingleKernel().invoke(
203 tempDbName, "$getResource");
204 }
205 } catch (Exception ignored) {
206 }
207 }
208 }
209
210 return null;
211 }
212
213 }