001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.common.utils;
042:
043: import java.net.URL;
044: import java.net.URLClassLoader;
045: import java.sql.Connection;
046: import java.sql.Driver;
047: import java.sql.SQLException;
048: import java.util.Properties;
049: import java.io.File;
050: import java.io.FileInputStream;
051: import java.io.FileNotFoundException;
052: import java.io.IOException;
053: import org.netbeans.api.db.explorer.ConnectionManager;
054: import org.netbeans.api.db.explorer.DatabaseConnection;
055: import org.netbeans.api.db.explorer.JDBCDriver;
056: import org.netbeans.api.db.explorer.JDBCDriverManager;
057: import org.netbeans.modules.mashup.db.ui.AxionDBConfiguration;
058: import com.sun.sql.framework.exception.DBSQLException;
059: import com.sun.sql.framework.utils.ScEncrypt;
060: import com.sun.sql.framework.jdbc.DBConnectionFactory;
061: import net.java.hulp.i18n.Logger;
062: import com.sun.sql.framework.utils.StringUtil;
063: import java.util.ArrayList;
064: import java.util.List;
065: import org.netbeans.modules.etl.logger.Localizer;
066: import org.netbeans.modules.etl.logger.LogUtil;
067: import org.netbeans.modules.etl.ui.ETLEditorSupport;
068: import org.openide.util.Exceptions;
069:
070: /**
071: *
072: * @author radval
073: *
074: */
075: public class DBExplorerUtil {
076:
077: public static final String AXION_DRIVER = "org.axiondb.jdbc.AxionDriver";
078: private static final String LOG_CATEGORY = DBExplorerUtil.class
079: .getName();
080: private static List localConnectionList = new ArrayList();
081: private static transient final Logger mLogger = LogUtil
082: .getLogger(DBExplorerUtil.class.getName());
083: private static transient final Localizer mLoc = Localizer.get();
084:
085: private static String adjustDatabaseURL(String url) {
086: if (url.indexOf(AXION_URL_PREFIX) != -1) {
087: String[] urlParts = parseConnUrl(url);
088: String relativePath = "\\nbproject\\private\\databases\\";
089: if (urlParts[1].startsWith(ETLEditorSupport.PRJ_PATH)) {
090: url = AXION_URL_PREFIX + ETLEditorSupport.PRJ_NAME
091: + "_" + urlParts[0] + ":" + urlParts[1];
092: } else if (urlParts[1].startsWith(relativePath)) {
093: url = AXION_URL_PREFIX + urlParts[0] + ":"
094: + ETLEditorSupport.PRJ_PATH + urlParts[1];
095: }
096: }
097:
098: return url;
099: }
100:
101: private static Properties loadAxionProperties() {
102: File conf = AxionDBConfiguration.getConfigFile();
103: Properties prop = new Properties();
104: try {
105: FileInputStream in = new FileInputStream(conf);
106: prop.load(in);
107: } catch (FileNotFoundException ex) {
108: //ignore
109: } catch (IOException ex) {
110: //ignore
111: }
112: return prop;
113: }
114:
115: private static JDBCDriver registerDriver(String driverName)
116: throws Exception {
117: JDBCDriver drv;
118:
119: if (driverName.equals(AXION_DRIVER)) {
120: drv = registerAxionDriverInstance();
121: } else {
122: drv = registerDriverInstance(driverName);
123: }
124:
125: return drv;
126: }
127:
128: /** Creates a new instance of DBExplorerUtil */
129: public DBExplorerUtil() {
130: }
131:
132: public static Connection createConnection(Properties connProps)
133: throws DBSQLException {
134: String driver = connProps
135: .getProperty(DBConnectionFactory.PROP_DRIVERCLASS);
136: String username = connProps
137: .getProperty(DBConnectionFactory.PROP_USERNAME);
138: String password = connProps
139: .getProperty(DBConnectionFactory.PROP_PASSWORD);
140: String url = connProps
141: .getProperty(DBConnectionFactory.PROP_URL);
142: return createConnection(driver, url, username, password);
143: }
144:
145: public static final String AXION_URL_PREFIX = "jdbc:axiondb:";
146:
147: public static String[] parseConnUrl(String url) {
148: String name, workDir;
149: String prefixStripped = url
150: .substring(AXION_URL_PREFIX.length());
151: int colon = prefixStripped.indexOf(":");
152: if (colon == -1 || (prefixStripped.length() - 1 == colon)) {
153: name = prefixStripped;
154: workDir = name;
155: } else {
156: name = prefixStripped.substring(0, colon);
157: workDir = unifyPath(prefixStripped.substring(colon + 1));
158: }
159:
160: String[] connStr = new String[2];
161: connStr[0] = name;
162: connStr[1] = workDir;
163: return connStr;
164: }
165:
166: public static Connection createConnection(DatabaseConnection dbConn)
167: throws DBSQLException {
168: Connection conn = null;
169: if (dbConn != null) {
170: conn = createConnection(dbConn.getDriverClass(), dbConn
171: .getDatabaseURL(), dbConn.getUser(), dbConn
172: .getPassword());
173: }
174: return conn;
175: }
176:
177: public static Connection createConnection(String driverName,
178: String url, String username, String password)
179: throws DBSQLException {
180: // Try to get the connection directly. Dont go through DB Explorer.
181: // It may pop up a window asking for password.
182: JDBCDriver drv = null;
183: Connection conn = null;
184: try {
185: url = adjustDatabaseURL(url);
186: drv = registerDriver(driverName);
187:
188: conn = getConnection(drv, driverName, url, username,
189: password);
190: if (conn == null) { // get from db explorer
191: DatabaseConnection dbConn = createDatabaseConnection(
192: driverName, url, username, password);
193: try {
194: if (dbConn != null) {
195: conn = dbConn.getJDBCConnection();
196: if (conn == null) { // make a final try
197: ConnectionManager.getDefault()
198: .showConnectionDialog(dbConn);
199: Thread.sleep(5000);
200: conn = dbConn.getJDBCConnection();
201: }
202: }
203: } catch (Exception ex) {
204: // ignore
205: }
206:
207: // If connection is still nul throw exception
208: if (conn == null) {
209: throw new DBSQLException(
210: "Connection could not be established. Please check the Database Server.");
211: }
212: } else {
213: synchronized (localConnectionList) {
214: localConnectionList.add(conn);
215: }
216: }
217: } catch (Exception ex) {
218: Exceptions.printStackTrace(ex);
219: }
220: return conn;
221: }
222:
223: public static void closeIfLocalConnection(Connection conn) {
224: if (localConnectionList.contains(conn)) {
225: try {
226: localConnectionList.remove(conn);
227: conn.close();
228: } catch (SQLException ex) {
229: Exceptions.printStackTrace(ex);
230: }
231: }
232: }
233:
234: public static DatabaseConnection createDatabaseConnection(
235: String driverName, String url, String username,
236: String password) throws DBSQLException {
237: DatabaseConnection dbconn = null;
238: JDBCDriver drv = null;
239: String schema = null;
240: try {
241:
242: url = adjustDatabaseURL(url);
243: drv = registerDriver(driverName);
244:
245: // check if connection exists in DB Explorer. Else add the connection to DB Explorer.
246:
247: DatabaseConnection[] dbconns = ConnectionManager
248: .getDefault().getConnections();
249: for (int i = 0; i < dbconns.length; i++) {
250: if (dbconns[i].getDriverClass().equals(driverName)
251: && dbconns[i].getDatabaseURL().equals(url)
252: && dbconns[i].getUser().equals(username)) {
253: dbconn = dbconns[i];
254: break;
255: }
256: }
257:
258: // dont add instance db and monitor db and local dbs connections to db explorer.
259: if (dbconn == null) {
260: if (url.startsWith(AXION_URL_PREFIX)) {
261: schema = "";
262: } else {
263: schema = username.toUpperCase();
264: }
265: dbconn = DatabaseConnection.create(drv, url, username,
266: schema, password, true);
267:
268: if (url.indexOf("InstanceDB") == -1
269: && url.indexOf("MonitorDB") == -1
270: && url.indexOf(ETLEditorSupport.PRJ_PATH) == -1) {
271: ConnectionManager.getDefault()
272: .addConnection(dbconn);
273: }
274: }
275:
276: return dbconn;
277:
278: } catch (Exception e) {
279: throw new DBSQLException(
280: "Connection could not be established.", e);
281: }
282: }
283:
284: /**
285: * Registers an instance of Driver associated with the given driver class name. Does
286: * nothing if an instance has already been registered with the JDBC DriverManager.
287: *
288: * @param driverName class name of driver to be created
289: * @return Driver instance associated with <code>driverName</code>
290: * @throws Exception if error occurs while creating or looking up the desired driver
291: * instance
292: */
293: public static JDBCDriver registerDriverInstance(
294: final String driverName) throws Exception {
295: JDBCDriver driver = null;
296: JDBCDriver[] drivers;
297: try {
298: drivers = JDBCDriverManager.getDefault().getDrivers(
299: driverName);
300: } catch (Exception ex) {
301: throw new Exception("Invalid driver name specified.");
302: }
303: if (driverName.equals(AXION_DRIVER)) {
304: driver = registerAxionDriverInstance();
305: } else {
306: if (drivers.length == 0) {
307: throw new Exception(
308: "Specified JDBC Driver not found in DB Explorer.");
309: } else {
310: driver = drivers[0];
311: }
312: }
313: return driver;
314: }
315:
316: private static JDBCDriver registerAxionDriverInstance()
317: throws Exception {
318: JDBCDriver driver = null;
319: String driverName = AXION_DRIVER;
320: JDBCDriver[] drivers = JDBCDriverManager.getDefault()
321: .getDrivers(driverName);
322: if (drivers.length == 0) {
323: // if axion db driver not available in db explorer, add it.
324: URL[] url = new URL[1];
325: String workDir = getDefaultAxionDriverLoc();
326: if (StringUtil.isNullString(workDir)) {
327: throw new Exception("Axion Driver could not be located");
328: }
329: url[0] = new URL("file:/" + workDir);
330: driver = JDBCDriver.create(driverName, "Mashup DB",
331: driverName, url);
332: JDBCDriverManager.getDefault().addDriver(driver);
333: }
334: if (driver == null) {
335: for (int i = 0; i < drivers.length; i++) {
336: if (drivers[i].getClassName().equals(driverName)) {
337: driver = drivers[i];
338: break;
339: }
340: }
341: }
342: return driver;
343: }
344:
345: /**
346: * Manually load the driver class and get the connection for the specified properties.
347: *
348: * @return connection for the corresponding db url and properties.
349: */
350: private static Connection getConnection(JDBCDriver drv,
351: String driverName, String url, String username,
352: String password) {
353: Connection conn = null;
354: Driver newDriverClass = null;
355: try {
356: // get the driver jar files and load them manually
357: URL[] urls = drv.getURLs();
358: ClassLoader cl = new URLClassLoader(urls, Thread
359: .currentThread().getContextClassLoader());
360: newDriverClass = (Driver) cl.loadClass(driverName)
361: .newInstance();
362: Properties prop = new Properties();
363: prop.setProperty("user", username);
364: prop.setProperty("password", password);
365: conn = newDriverClass.connect(url, prop);
366: } catch (SQLException ex) {
367: try {
368: // may be some class forgot to decrypt the password. Check if this one works
369: Properties prop = new Properties();
370: prop.setProperty("user", username);
371: // if its not an encrypted password, decrypt operation will fail. Caught as general Exception
372: password = ScEncrypt.decrypt(username, password);
373: prop.setProperty("password", password);
374: conn = newDriverClass.connect(url, prop);
375: } catch (SQLException e) {
376: mLogger
377: .infoNoloc(mLoc
378: .t(
379: "PRSR098: Unable to get the specified connection directly.{0}",
380: LOG_CATEGORY));
381: } catch (Exception numex) {
382: mLogger
383: .infoNoloc(mLoc
384: .t(
385: "PRSR099: Unable to get the specified connection directly.{0}",
386: LOG_CATEGORY));
387: }
388: } catch (Exception ex) {
389: mLogger
390: .infoNoloc(mLoc
391: .t(
392: "PRSR100: Unable to find the driver class in the specified jar file{0}",
393: LOG_CATEGORY));
394: }
395: return conn;
396: }
397:
398: /*
399: * Returns the default location of axiondb.jar along with the dependencies.
400: *
401: */
402: public static String getDefaultAxionWorkingFolder() {
403: Properties prop = loadAxionProperties();
404: return prop.getProperty(AxionDBConfiguration.PROP_DB_LOC);
405: }
406:
407: public static String getDefaultAxionDriverLoc() {
408: Properties prop = loadAxionProperties();
409: return prop.getProperty(AxionDBConfiguration.PROP_DRIVER_LOC);
410: }
411:
412: public static void recreateMissingFlatfileConnectionInDBExplorer() {
413: // add flatfile databases to db explorer.
414: String workDir = getDefaultAxionWorkingFolder();
415: File f = new File(workDir);
416: File[] db = null;
417: if (f.exists()) {
418: db = f.listFiles();
419: for (int i = 0; i < db.length; i++) {
420: String ver = null;
421: try {
422: ver = db[i].getCanonicalPath() + "\\"
423: + db[i].getName().toUpperCase() + ".VER";
424: File version = new File(ver);
425: if (version.exists()) {
426: String url = AXION_URL_PREFIX + db[i].getName()
427: + ":" + workDir + db[i].getName();
428: url = unifyPath(url);
429: DatabaseConnection con = ConnectionManager
430: .getDefault().getConnection(url);
431: if (con == null) {
432: DBExplorerUtil.createDatabaseConnection(
433: AXION_DRIVER, url, "sa", "sa");
434: }
435: }
436: } catch (Exception ex) {
437: //ignore
438: }
439: }
440: }
441: }
442:
443: public static String unifyPath(String workDir) {
444: return workDir.replace('/', '\\');
445: }
446:
447: public static List<DatabaseConnection> getDatabasesForCurrentProject() {
448: List<DatabaseConnection> dbConns = new ArrayList<DatabaseConnection>();
449: String workDir = ETLEditorSupport.PRJ_PATH
450: + "\\nbproject\\private\\databases\\";
451: File f = new File(workDir);
452: File[] db = null;
453: if (f.exists()) {
454: db = f.listFiles();
455: for (int i = 0; i < db.length; i++) {
456: String ver = null;
457: try {
458: ver = db[i].getCanonicalPath()
459: + "\\"
460: + (ETLEditorSupport.PRJ_NAME + "_" + db[i]
461: .getName()).toUpperCase() + ".VER";
462: File version = new File(ver);
463: if (version.exists()) {
464: String url = DBExplorerUtil.AXION_URL_PREFIX
465: + db[i].getName() + ":" + workDir
466: + db[i].getName();
467: url = unifyPath(url);
468: DatabaseConnection dbConn = DBExplorerUtil
469: .createDatabaseConnection(
470: "org.axiondb.jdbc.AxionDriver",
471: url, "sa", "sa");
472: dbConns.add(dbConn);
473: }
474: } catch (Exception ex) {
475: //ignore
476: }
477: }
478: }
479: return dbConns;
480: }
481:
482: public static String getDisplayName(DatabaseConnection dbConn) {
483: if (dbConn.toString() == null) {
484: return "<None>";
485: }
486:
487: String connName = dbConn.getName();
488: if (connName.startsWith(DBExplorerUtil.AXION_URL_PREFIX)) {
489: String[] parts = DBExplorerUtil.parseConnUrl(connName);
490: connName = parts[0] + " [MASHUP DB]";
491: } else if (connName.startsWith("jdbc:derby://")) {
492: int start = "jdbc:derby://".length();
493: String host = connName.substring(start);
494: host = host.substring(0, host.indexOf(":"));
495: String dbName = connName.substring(start + host.length());
496: start = dbName.indexOf("/") + 1;
497: dbName = dbName.substring(start, dbName.indexOf("["));
498: connName = dbName.trim() + "@" + host + " [DERBY]";
499: }
500: return connName;
501: }
502: }
|