diff --git a/db/src/org/netbeans/api/db/explorer/JDBCDriver.java b/db/src/org/netbeans/api/db/explorer/JDBCDriver.java --- a/db/src/org/netbeans/api/db/explorer/JDBCDriver.java +++ b/db/src/org/netbeans/api/db/explorer/JDBCDriver.java @@ -44,18 +44,33 @@ package org.netbeans.api.db.explorer; +import java.net.MalformedURLException; import java.net.URL; import java.sql.Driver; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.netbeans.api.project.libraries.Library; +import org.netbeans.api.project.libraries.LibraryManager; import org.netbeans.modules.db.explorer.DbDriverManager; +import org.netbeans.spi.project.libraries.LibraryFactory; +import org.netbeans.spi.project.libraries.LibraryImplementation3; +import org.netbeans.spi.project.libraries.support.LibrariesSupport; /** * Encapsulates a JDBC driver. */ public final class JDBCDriver { + private static Pattern jarFileNamePattern = null; private URL[] urls; private String clazz; private String displayName; @@ -140,6 +155,103 @@ throw new DatabaseException(sqle); } } + + /** + * Get library corresponding to the JDBC driver. If corresponding registered + * library is found, it will be used (it applies only for drivers that are + * shipped with NetBeans IDE). Otherwise a new library is created. + * + * @return The library that contains the JDBC Driver. A existing registered + * library, or a newly created one. If the library cannot be created (e.g. + * there are no JAR files associated with the driver), return null. + */ + public Library getDriverLibrary() { + String libraryName = null; + switch (getClassName()) { + case "com.mysql.jdbc.Driver": //NOI18N + libraryName = "MySQLDriver"; //NOI18N + break; + case "org.postgresql.Driver": //NOI18N + libraryName = "PostgreSQLDriver"; //NOI18N + break; + case "org.apache.derby.jdbc.EmbeddedDriver": //NOI18N + case "org.apache.derby.jdbc.ClientDriver": //NOI18N + libraryName = "JAVADB_DRIVER_LABEL"; //NOI18N + break; + } + if (libraryName != null) { + Library lib = LibraryManager.getDefault().getLibrary(libraryName); + if (lib != null && checkLibraryContainsDriverJARs(lib)) { + return lib; + } + } + return createLibraryForDriver(); + } + + /** + * Check whether the registered library contains all JARs needed by the + * driver, and that it doesn't contain extra files. + */ + private boolean checkLibraryContainsDriverJARs(Library lib) { + Set filesInLib = new HashSet<>(); + for (URL url : lib.getContent("classpath")) { //NOI18N + String jarFileName = getJarFileName(url); + if (jarFileName != null) { + filesInLib.add(jarFileName); + } + } + for (URL url : getURLs()) { + String jarFileName = getJarFileName(url); + if (jarFileName == null || !filesInLib.contains(jarFileName)) { + return false; + } + } + int allowedFiles = "JAVADB_DRIVER_LABEL".equals(lib.getName()) //NOI18N + ? 3 : 1; + return filesInLib.size() <= allowedFiles; + } + + /** + * Create a library containing all JARs of this JDBC driver. + */ + private Library createLibraryForDriver() { + List libraryContentURLs = new ArrayList<>(urls.length); + for (URL url : urls) { + if (url.toString().matches(".*\\.jar")) {//NOI18N + try { + libraryContentURLs.add( + new URL("jar:" + url.toString() + "!/")); //NOI18N + } catch (MalformedURLException ex) { + Logger.getLogger(JDBCDriver.class.getName()).log(Level.INFO, + null, ex); + } + } else { + return null; + } + } + if (libraryContentURLs.isEmpty()) { + return null; + } else { + LibraryImplementation3 libImpl + = LibrariesSupport.createLibraryImplementation3( + "j2se", "classpath", "src", "javadoc"); //NOI18N + libImpl.setContent("classpath", libraryContentURLs); //NOI18N + return LibraryFactory.createLibrary(libImpl); + } + } + + /** + * Extract name of JAR file (without path and extension) from library + * content URL or driver JAR URL + */ + private String getJarFileName(URL url) { + if (jarFileNamePattern == null) { + jarFileNamePattern = Pattern.compile( + ".*/([^/]*).jar(?:!/)?"); //NOI18N + } + Matcher m = jarFileNamePattern.matcher(url.toString()); + return m.matches() ? m.group(1) : null; + } public String toString() { return "JDBCDriver[name='" + name + // NOI18N diff --git a/derby/src/org/netbeans/modules/derby/DerbyOptions.java b/derby/src/org/netbeans/modules/derby/DerbyOptions.java --- a/derby/src/org/netbeans/modules/derby/DerbyOptions.java +++ b/derby/src/org/netbeans/modules/derby/DerbyOptions.java @@ -407,8 +407,9 @@ outStreamd = derbyLib.getOutputStream(ld); osw = new OutputStreamWriter(outStreamd); outd = new BufferedWriter(osw); - outd.write("\n\n");//NOI18N - outd.write("\nJAVADB_DRIVER_LABEL\n");//NOI18N + outd.write("\n"); //NOI18N + outd.write("\n"); //NOI18N + outd.write("JAVADB_DRIVER_LABEL\n");//NOI18N outd.write("j2se\n");//NOI18N outd.write("org.netbeans.modules.derby.Bundle\n");//NOI18N outd.write("\nclasspath\n"); //NOI18N @@ -417,7 +418,18 @@ outd.write("jar:" + new File(location.getAbsolutePath() + "/lib/derbynet.jar").toURI().toURL() + "!/\n"); //NOI18N outd.write("\n\nsrc\n\n"); //NOI18N outd.write("\njavadoc\n"); //NOI18N - outd.write("\n"); //NOI18N + outd.write("\n"); //NOI18N + outd.write("\n"); //NOI18N + outd.write(" \n"); //NOI18N + outd.write(" maven-dependencies\n"); //NOI18N + outd.write(" \n"); //NOI18N + outd.write(" org.apache.derby:derby:10.10.1.1:jar\n"); //NOI18N + outd.write(" org.apache.derby:derbyclient:10.10.1.1:jar\n"); //NOI18N + outd.write(" org.apache.derby:derbynet:10.10.1.1:jar\n"); //NOI18N + outd.write(" \n"); //NOI18N + outd.write(" \n"); //NOI18N + outd.write("\n"); //NOI18N + outd.write(""); //NOI18N } } finally { if (null != outd) {