diff --git a/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.form b/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.form
index 67e6ca091..6d37fbe90 100644
--- a/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.form
+++ b/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.form
@@ -449,6 +449,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.java b/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.java
index 768bc058b..23bf41ffd 100644
--- a/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.java
+++ b/src/main/gui/net/sf/jailer/ui/DbConnectionDetailsEditor.java
@@ -27,7 +27,11 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -35,8 +39,14 @@ import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.Timer;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
import net.sf.jailer.ui.DbConnectionDialog.ConnectionInfo;
+import net.sf.jailer.ui.util.ConcurrentTaskControl;
+import net.sf.jailer.ui.util.HttpDownload;
+import net.sf.jailer.util.CsvFile;
+import net.sf.jailer.util.CsvFile.Line;
/**
* "Connect with DB" dialog.
@@ -104,6 +114,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
}
private final Window parent;
+ private List driverlist;
/** Creates new form DbConnectionDialog
* @param forNew
@@ -128,6 +139,32 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
dbUrl,
user
};
+ try {
+ CsvFile drivers = new CsvFile(Environment.newWorkingFolderFile("driverlist.csv"));
+ driverlist = new ArrayList(drivers.getLines());
+ } catch (Throwable t) {
+ driverlist = null;
+ }
+
+ Arrays.asList(jar1, jar2, jar3, jar4, dbUrl).forEach(f -> f.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ check();
+ }
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ check();
+ }
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ check();
+ }
+ private void check() {
+ List driverURLs = retrieveDriverURLs(driverlist);
+ downloadButton.setEnabled(driverURLs != null
+ && Arrays.asList(jar1, jar2, jar3, jar4).stream().allMatch(f -> f.getText().trim().isEmpty()));
+ }
+ }));
if (needsTest) {
testConnectionButton.setVisible(false);
} else {
@@ -212,8 +249,41 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
addWindowListener(new WindowAdapter() {
@Override
- public void windowOpened(WindowEvent e) {
+ public void windowOpened(WindowEvent evt) {
alias.grabFocus();
+ UIUtil.invokeLater(4, () -> {
+ List driverURLs = retrieveDriverURLs(driverlist);
+ if (forNew && driverURLs != null && downloadButton.isEnabled() && driverURLs.stream().allMatch(
+ url -> {
+ try {
+ return new File(Environment.newFile(HttpDownload.DOWNLOADFOLDER), HttpDownload.toFileName(new URL(url))).exists();
+ } catch (Exception e) {
+ return false;
+ }
+ })) {
+ UIUtil.invokeLater(() -> {
+ List files = driverURLs.stream().map(url -> {
+ try {
+ return new File(Environment.newFile(HttpDownload.DOWNLOADFOLDER), HttpDownload.toFileName(new URL(url))).getAbsolutePath();
+ } catch (Exception e) {
+ return "";
+ }
+ }).collect(Collectors.toList());
+ if (files.size() > 0) {
+ jar1.setText(files.get(0));
+ }
+ if (files.size() > 1) {
+ jar2.setText(files.get(1));
+ }
+ if (files.size() > 2) {
+ jar3.setText(files.get(2));
+ }
+ if (files.size() > 3) {
+ jar4.setText(files.get(3));
+ }
+ });
+ }
+ });
}
@Override
public void windowClosed(WindowEvent e) {
@@ -231,6 +301,17 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
UIUtil.initPeer();
}
+ protected List retrieveDriverURLs(List driverlist) {
+ if (driverlist != null) {
+ String url = dbUrl.getText().trim().replaceAll("^(\\w+:\\w+:).*", "$1");
+ Line line = driverlist.stream().filter(l -> l.cells.get(1).startsWith(url)).findFirst().orElse(null);
+ if (line != null && !line.cells.get(4).isEmpty()) {
+ return new ArrayList(Arrays.asList(line.cells.get(4).split("\\s+")));
+ }
+ }
+ return null;
+ }
+
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
@@ -280,6 +361,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
importCBButton = new javax.swing.JButton();
feedbackLabel = new javax.swing.JLabel();
jSeparator1 = new javax.swing.JSeparator();
+ downloadButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Database Connection");
@@ -624,6 +706,20 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
gridBagConstraints.insets = new java.awt.Insets(0, 2, 16, 0);
jPanel1.add(jSeparator1, gridBagConstraints);
+ downloadButton.setText("Download Driver");
+ downloadButton.setEnabled(false);
+ downloadButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ downloadButtonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 44;
+ gridBagConstraints.gridwidth = 3;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
+ jPanel1.add(downloadButton, gridBagConstraints);
+
getContentPane().add(jPanel1, "card2");
pack();
@@ -753,6 +849,86 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
Toolkit.getDefaultToolkit().beep();
}//GEN-LAST:event_importCBButtonActionPerformed
+ private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
+ List driverURLs = retrieveDriverURLs(driverlist);
+ if (driverURLs != null) {
+ final List files;
+ final Object LOCK = new Object();
+ synchronized (LOCK) {
+ files = new ArrayList();
+ }
+
+ AtomicBoolean ok = new AtomicBoolean(true);
+
+ @SuppressWarnings("serial")
+ final ConcurrentTaskControl concurrentTaskControl = new ConcurrentTaskControl(
+ this, "Downloading Driver") {
+
+ @Override
+ protected void onError(Throwable error) {
+ UIUtil.showException(this, "Error", error);
+ ok.set(false);
+ closeWindow();
+ }
+
+ @Override
+ protected void onCancellation() {
+ ok.set(false);
+ closeWindow();
+ }
+ };
+
+ ConcurrentTaskControl.openInModalDialog(this, concurrentTaskControl,
+ new ConcurrentTaskControl.Task() {
+ @Override
+ public void run() throws Throwable {
+ long[] total = { 0 };
+ driverURLs.forEach(url -> {
+ try {
+ String result = HttpDownload.get(url, vol -> {
+ UIUtil.invokeLater(() -> {
+ total[0] += vol;
+ concurrentTaskControl.master.infoLabel.setText("Downloading... (" + total[0] / 1024 + "k)");
+ });
+ });
+ if (result.length() == 0) {
+ throw new RuntimeException("cannot download \"" + url + "\"");
+ }
+ synchronized (LOCK) {
+ files.add(result.toString());
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException("cannot download \"" + url + "\"", t);
+ }
+ });
+
+ UIUtil.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (ok.get()) {
+ synchronized (LOCK) {
+ if (files.size() > 0) {
+ jar1.setText(files.get(0));
+ }
+ if (files.size() > 1) {
+ jar2.setText(files.get(1));
+ }
+ if (files.size() > 2) {
+ jar3.setText(files.get(2));
+ }
+ if (files.size() > 3) {
+ jar4.setText(files.get(3));
+ }
+ }
+ }
+ concurrentTaskControl.closeWindow();
+ }
+ });
+ }
+ }, "Downloading Driver");
+ }
+ }//GEN-LAST:event_downloadButtonActionPerformed
+
protected void onSelect() {
}
@@ -760,6 +936,7 @@ public class DbConnectionDetailsEditor extends javax.swing.JDialog {
public javax.swing.JTextField alias;
private javax.swing.JButton cancelButton;
public javax.swing.JTextField dbUrl;
+ private javax.swing.JButton downloadButton;
public javax.swing.JTextField driverClass;
private javax.swing.JButton exportCBButton;
private javax.swing.JLabel feedbackLabel;
diff --git a/src/main/gui/net/sf/jailer/ui/util/HttpDownload.java b/src/main/gui/net/sf/jailer/ui/util/HttpDownload.java
new file mode 100644
index 000000000..a707c0eac
--- /dev/null
+++ b/src/main/gui/net/sf/jailer/ui/util/HttpDownload.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2007 - 2020 Ralf Wisser.
+ *
+ * Licensed 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 net.sf.jailer.ui.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.function.Consumer;
+
+import net.sf.jailer.ui.Environment;
+
+public class HttpDownload {
+
+ public static final String DOWNLOADFOLDER = "download";
+
+ public static String get(final String url, Consumer volConsumer) throws Throwable {
+ Throwable t = null;
+ StringBuilder result = new StringBuilder();
+ try {
+ if (get(url, result, volConsumer) == 200) {
+ return result.toString();
+ }
+ } catch (Throwable err) {
+ t = err;
+ }
+ try {
+ result = new StringBuilder();
+ Process p = Runtime.getRuntime().exec("java -classpath " + Environment.newWorkingFolderFile("jailer.jar").getPath() + " -Djava.net.useSystemProxies=true " + HttpDownload.class.getName() + " " + url);
+ BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+
+ while ((line = input.readLine()) != null) {
+ result.append(line);
+ }
+
+ input.close();
+ } catch (Throwable err) {
+ err.printStackTrace();
+ if (t != null) {
+ throw t;
+ }
+ }
+ return result.toString();
+ }
+
+ public static int get(final String url, final StringBuilder result, Consumer volConsumer) throws MalformedURLException, IOException {
+ URL theUrl;
+ theUrl = new URL(url);
+ long t0 = System.currentTimeMillis();
+ URLConnection con = theUrl.openConnection();
+ ((HttpURLConnection) con).setInstanceFollowRedirects(true);
+ InputStream in = con.getInputStream();
+ int rc = ((HttpURLConnection) con).getResponseCode();
+ if (rc == 200) {
+ File dir = Environment.newFile(DOWNLOADFOLDER);
+ dir.mkdir();
+ String name = toFileName(theUrl);
+ File tmpFile = new File(dir, name + "." + System.currentTimeMillis());
+ File file = new File(dir, name);
+ if (!file.exists()) {
+ OutputStream out = new FileOutputStream(tmpFile);
+ int c;
+ long total = 0;
+ long vol = 0;
+ while ((c = in.read()) != -1) {
+ out.write((char) c);
+ ++total;
+ ++vol;
+ long t1 = System.currentTimeMillis();
+ if (t1 - t0 > 1000) {
+ t0 = t1;
+ if (volConsumer != null) {
+ volConsumer.accept(vol);
+ }
+ vol = 0;
+ }
+ }
+ out.close();
+ if (!tmpFile.renameTo(file)) {
+ throw new RuntimeException("can't rename \"" + tmpFile.getAbsolutePath() + "\"");
+ };
+ if (total < 1024 * 100L) {
+ return 0;
+ }
+ }
+ in.close();
+ result.append(new File(DOWNLOADFOLDER, name).getAbsolutePath());
+ }
+ return rc;
+ }
+
+ public static String toFileName(URL theUrl) {
+ String name = theUrl.getPath().replaceAll("^.*/([^/]+)$", "$1");
+ return name;
+ }
+
+ public static void main(String args[]) {
+ final StringBuilder result = new StringBuilder();
+ try {
+ get(args[0], result, null);
+ System.out.println(result);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+}