This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/master by this push:
     new bf31182  CAY-2656 Modeler: option to download required jars directly 
from maven central
     new 325ecff  Merge pull request #420 from 
stariy95/4.2-FEATURE-modeler-classpath-download-from-central
bf31182 is described below

commit bf311828c0e67aeae92822665abd503e4c8446aa
Author: Nikita Timofeev <stari...@gmail.com>
AuthorDate: Thu Apr 30 14:06:26 2020 +0300

    CAY-2656 Modeler: option to download required jars directly from maven 
central
---
 .../modeler/dialog/pref/ClasspathPreferences.java  | 113 ++++++++--------
 .../dialog/pref/ClasspathPreferencesView.java      |   7 +
 .../modeler/dialog/pref/MavenDependencyDialog.java | 148 +++++++++++++++++++++
 .../dialog/pref/MavenDependencyDialogView.java     | 101 ++++++++++++++
 4 files changed, 310 insertions(+), 59 deletions(-)

diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferences.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferences.java
index e3cf205..052cdf1 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferences.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferences.java
@@ -43,12 +43,13 @@ public class ClasspathPreferences extends CayenneController 
{
 
     private static final Logger logger = 
LoggerFactory.getLogger(ClasspathPreferences.class);
 
-    protected ClasspathPreferencesView view;
-    protected List<String> classPathEntries;
-    protected ClasspathTableModel tableModel;
-    protected CayennePreferenceEditor editor;
-    protected List<String> classPathKeys;
-    private Preferences preferences;
+    private final ClasspathPreferencesView view;
+    private final List<String> classPathEntries;
+    private final List<String> classPathKeys;
+    private final ClasspathTableModel tableModel;
+    private final CayennePreferenceEditor editor;
+    private final Preferences preferences;
+
     private int counter;
 
     public ClasspathPreferences(PreferenceDialog parentController) {
@@ -56,29 +57,24 @@ public class ClasspathPreferences extends CayenneController 
{
 
         this.view = new ClasspathPreferencesView();
 
+        PreferenceEditor editor = parentController.getEditor();
+        this.editor = editor instanceof CayennePreferenceEditor
+                ? (CayennePreferenceEditor) editor
+                : null;
+
         // this prefs node is shared with other dialog panels... be aware of
         // that when accessing the keys
         this.preferences = 
getApplication().getPreferencesNode(this.getClass(), "");
 
-        PreferenceEditor editor = parentController.getEditor();
-        if (editor instanceof CayennePreferenceEditor) {
-            this.editor = (CayennePreferenceEditor) editor;
-        }
-
-        List<String> classPathEntries = new ArrayList<String>();
-        List<String> classPathKeys = new ArrayList<String>();
-
-        this.counter = loadPreferences(classPathEntries, classPathKeys);
-
-        this.classPathEntries = classPathEntries;
-        this.classPathKeys = classPathKeys;
-
-        this.tableModel = new ClasspathTableModel();
+        this.classPathEntries = new ArrayList<>();
+        this.classPathKeys = new ArrayList<>();
+        this.counter = loadPreferences();
+        this.tableModel = new ClasspathTableModel(classPathEntries);
 
         initBindings();
     }
 
-    private int loadPreferences(List<String> classPathEntries, List<String> 
classPathKeys) {
+    private synchronized int loadPreferences() {
 
         String[] cpKeys;
         try {
@@ -89,13 +85,12 @@ public class ClasspathPreferences extends CayenneController 
{
         }
 
         int max = 0;
-
         for (String cpKey : cpKeys) {
-
-            int c;
-
             try {
-                c = Integer.parseInt(cpKey);
+                int c = Integer.parseInt(cpKey);
+                if (c > max) {
+                    max = c;
+                }
             } catch (NumberFormatException e) {
                 // we are sharing the 'preferences' node with other dialogs, 
and
                 // this is a rather poor way of telling our preference keys 
from
@@ -106,10 +101,6 @@ public class ClasspathPreferences extends 
CayenneController {
                 continue;
             }
 
-            if (c > max) {
-                max = c;
-            }
-
             String tempValue = preferences.get(cpKey, "");
             if (!"".equals(tempValue)) {
                 classPathEntries.add(tempValue);
@@ -127,8 +118,9 @@ public class ClasspathPreferences extends CayenneController 
{
     protected void initBindings() {
         view.getTable().setModel(tableModel);
         view.getAddDirButton().addActionListener(e -> 
addClassDirectoryAction());
-        view.getRemoveEntryButton().addActionListener(e -> 
removeEntryAction());
         view.getAddJarButton().addActionListener(e -> addJarOrZipAction());
+        view.getAddMvnButton().addActionListener(e -> 
addMvnDependencyAction());
+        view.getRemoveEntryButton().addActionListener(e -> 
removeEntryAction());
     }
 
     protected void addJarOrZipAction() {
@@ -139,13 +131,18 @@ public class ClasspathPreferences extends 
CayenneController {
         chooseClassEntry(null, "Select Java Class Directory.", 
JFileChooser.DIRECTORIES_ONLY);
     }
 
-    protected void removeEntryAction() {
+    protected void addMvnDependencyAction() {
+        MavenDependencyDialog dialog = new MavenDependencyDialog(this);
+        dialog.getView().setVisible(true);
+    }
+
+    protected synchronized void removeEntryAction() {
         int selected = view.getTable().getSelectedRow();
         if (selected < 0) {
             return;
         }
 
-        addRemovedPreferences(classPathKeys.get(selected));
+        updatePreferences(classPathKeys.get(selected), "");
         classPathEntries.remove(selected);
         classPathKeys.remove(selected);
 
@@ -157,13 +154,10 @@ public class ClasspathPreferences extends 
CayenneController {
         chooser.setFileSelectionMode(selectionMode);
         chooser.setDialogType(JFileChooser.OPEN_DIALOG);
         chooser.setAcceptAllFileFilterUsed(true);
-
         getLastDirectory().updateChooser(chooser);
-
         if (filter != null) {
             chooser.addChoosableFileFilter(filter);
         }
-
         chooser.setDialogTitle(title);
 
         File selected = null;
@@ -172,25 +166,29 @@ public class ClasspathPreferences extends 
CayenneController {
             selected = chooser.getSelectedFile();
         }
 
-        if (selected != null) {
-            if (!classPathEntries.contains(selected.getAbsolutePath())) {
-                // store last dir in preferences
-                getLastDirectory().updateFromChooser(chooser);
+        // store last dir in preferences
+        getLastDirectory().updateFromChooser(chooser);
+        // add to classpath list
+        addClasspathEntry(selected);
+    }
 
-                int len = classPathEntries.size();
-                int key = ++counter;
+    public synchronized void addClasspathEntry(File selected) {
+        if (selected == null || 
classPathEntries.contains(selected.getAbsolutePath())) {
+            return;
+        }
 
-                String value = selected.getAbsolutePath();
-                addChangedPreferences(Integer.toString(key), value);
-                classPathEntries.add(value);
-                classPathKeys.add(Integer.toString(key));
+        int len = classPathEntries.size();
+        int key = ++counter;
 
-                tableModel.fireTableRowsInserted(len, len);
-            }
-        }
+        String value = selected.getAbsolutePath();
+        updatePreferences(Integer.toString(key), value);
+        classPathEntries.add(value);
+        classPathKeys.add(Integer.toString(key));
+
+        tableModel.fireTableRowsInserted(len, len);
     }
 
-    public void addChangedPreferences(String key, String value) {
+    public void updatePreferences(String key, String value) {
         Map<String, String> map = 
editor.getChangedPreferences().get(preferences);
         if (map == null) {
             map = new HashMap<>();
@@ -199,16 +197,13 @@ public class ClasspathPreferences extends 
CayenneController {
         editor.getChangedPreferences().put(preferences, map);
     }
 
-    public void addRemovedPreferences(String key) {
-        Map<String, String> map = 
editor.getRemovedPreferences().get(preferences);
-        if (map == null) {
-            map = new HashMap<>();
-        }
-        map.put(key, "");
-        editor.getRemovedPreferences().put(preferences, map);
-    }
+    static class ClasspathTableModel extends AbstractTableModel {
 
-    class ClasspathTableModel extends AbstractTableModel {
+        private final List<String> classPathEntries;
+
+        ClasspathTableModel(List<String> classPathEntries) {
+            this.classPathEntries = classPathEntries;
+        }
 
         public int getColumnCount() {
             return 1;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferencesView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferencesView.java
index 292d362..6b0574c 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferencesView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/ClasspathPreferencesView.java
@@ -37,6 +37,7 @@ public class ClasspathPreferencesView extends JPanel {
 
     protected JButton addJarButton;
     protected JButton addDirButton;
+    protected JButton addMvnButton;
     protected JButton removeEntryButton;
     protected JTable table;
 
@@ -45,6 +46,7 @@ public class ClasspathPreferencesView extends JPanel {
         // create widgets
         addJarButton = new JButton("Add Jar/Zip");
         addDirButton = new JButton("Add Class Folder");
+        addMvnButton = new JButton("Get From Maven Central");
         removeEntryButton = new JButton("Remove");
 
         table = new CayenneTable();
@@ -59,6 +61,7 @@ public class ClasspathPreferencesView extends JPanel {
 
         builder.append(addJarButton);
         builder.append(addDirButton);
+        builder.append(addMvnButton);
         builder.append(removeEntryButton);
 
         setLayout(new BorderLayout());
@@ -76,6 +79,10 @@ public class ClasspathPreferencesView extends JPanel {
         return addJarButton;
     }
 
+    public JButton getAddMvnButton() {
+        return addMvnButton;
+    }
+
     public JButton getRemoveEntryButton() {
         return removeEntryButton;
     }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialog.java
new file mode 100644
index 0000000..7c95097
--- /dev/null
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialog.java
@@ -0,0 +1,148 @@
+package org.apache.cayenne.modeler.dialog.pref;
+
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Window;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.Objects;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.util.CayenneController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MavenDependencyDialog extends CayenneController {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(MavenDependencyDialog.class);
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    private final ClasspathPreferences preferencesController;
+    private final MavenDependencyDialogView view;
+
+    private volatile boolean closing;
+
+    public MavenDependencyDialog(ClasspathPreferences preferencesController) {
+        this.preferencesController = preferencesController;
+        Window parentView = preferencesController.getView() instanceof Window
+                ? (Window) preferencesController.getView()
+                : 
SwingUtilities.getWindowAncestor(preferencesController.getView());
+        if(parentView instanceof Dialog) {
+            view = new MavenDependencyDialogView((Dialog) parentView);
+        } else {
+            view = new MavenDependencyDialogView((Frame) parentView);
+        }
+        initBindings();
+    }
+
+    private void initBindings() {
+        view.getDownloadButton().addActionListener(e -> loadArtifact());
+        view.getCancelButton().addActionListener(e -> close());
+    }
+
+    private void loadArtifact() {
+        // url template: 
https://repo1.maven.org/maven2/org/apache/cayenne/cayenne-server/4.2.M1/cayenne-server-4.2.M1.jar
+        String groupPath = view.getGroupId().getText().replace('.', 
'/').trim();
+        String artifactIdText = view.getArtifactId().getText().trim();
+        String versionText = view.getVersion().getText().trim();
+
+        if("".equals(groupPath)) {
+            JOptionPane.showMessageDialog(view, "Empty group Id", "Warning", 
JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        if("".equals(artifactIdText)) {
+            JOptionPane.showMessageDialog(view, "Empty artifact Id", 
"Warning", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        if("".equals(versionText)) {
+            JOptionPane.showMessageDialog(view, "Empty version", "Warning", 
JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        String urlText = "https://repo1.maven.org/maven2/"; + groupPath + "/"
+                + artifactIdText + "/" + versionText + "/"
+                + artifactIdText + "-" + versionText + ".jar";
+
+        Application.getInstance().getFrameController().updateStatus("Loading " 
+ urlText);
+
+        String localPath = System.getProperty( "user.home" ) + 
"/.cayenne/modeler/"
+                + groupPath + "/" + artifactIdText + "-" + versionText + 
".jar";
+        File targetFile = new File(localPath);
+
+        view.getDownloadButton().setEnabled(false);
+        new Thread(() -> download(urlText, targetFile)).start();
+    }
+
+    private void close() {
+        this.closing = true;
+        view.close();
+    }
+
+    public void download(String srcUrl, File dstFile) {
+        if(!dstFile.getParentFile().exists()
+                && !dstFile.getParentFile().mkdirs()) {
+            finalizeDownload(dstFile, "Unable to create file " + dstFile, 
false, false);
+            return;
+        }
+
+        try {
+            BufferedInputStream is = new BufferedInputStream(new 
URL(srcUrl).openStream());
+            OutputStream os = new FileOutputStream(dstFile);
+            transferTo(is, os);
+        } catch (FileNotFoundException fnf) {
+            finalizeDownload(dstFile, "Url not found: " + srcUrl, false, 
false);
+            return;
+        } catch (Exception e) {
+            LOGGER.warn("Failed to download Maven dependency " + srcUrl, e);
+            finalizeDownload(dstFile, "Unable to download file " + dstFile, 
false, true);
+            return;
+        }
+        finalizeDownload(dstFile, "Succesfully downloaded", true, true);
+    }
+
+    private void finalizeDownload(File dstFile, String status, boolean 
success, boolean shouldClose) {
+        SwingUtilities.invokeLater(() -> {
+            if(success) {
+                preferencesController.addClasspathEntry(dstFile);
+            } else {
+                JOptionPane.showMessageDialog(view, status, "Error", 
JOptionPane.ERROR_MESSAGE);
+            }
+
+            view.getDownloadButton().setEnabled(true);
+            
Application.getInstance().getFrameController().updateStatus(status);
+
+            if(shouldClose) {
+                close();
+            }
+        });
+    }
+
+    private void transferTo(InputStream in, OutputStream out) throws 
IOException {
+        Objects.requireNonNull(in);
+        Objects.requireNonNull(out);
+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+        int read;
+        while ((read = in.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
+            out.write(buffer, 0, read);
+            if(closing) {
+                break;
+            }
+        }
+    }
+
+    @Override
+    public Component getView() {
+        return view;
+    }
+}
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialogView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialogView.java
new file mode 100644
index 0000000..8ecc370
--- /dev/null
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/MavenDependencyDialogView.java
@@ -0,0 +1,101 @@
+package org.apache.cayenne.modeler.dialog.pref;
+
+import java.awt.BorderLayout;
+import java.awt.Dialog;
+import java.awt.Frame;
+
+import javax.swing.JButton;
+import javax.swing.JTextField;
+
+import com.jgoodies.forms.builder.PanelBuilder;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import org.apache.cayenne.modeler.util.CayenneDialog;
+import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.util.PanelFactory;
+
+public class MavenDependencyDialogView extends CayenneDialog {
+
+    private JButton downloadButton;
+    private JButton cancelButton;
+    private JTextField groupId;
+    private JTextField artifactId;
+    private JTextField version;
+
+    public MavenDependencyDialogView(Dialog parentDialog) {
+        super(parentDialog, "Download artifact", true);
+        this.initView();
+        this.pack();
+        ModelerUtil.centerWindow(parentDialog, this);
+    }
+
+    public MavenDependencyDialogView(Frame parentFrame) {
+        super(parentFrame, "Download artifact", true);
+        this.initView();
+        this.pack();
+        ModelerUtil.centerWindow(parentFrame, this);
+    }
+
+    private void initView() {
+        getContentPane().setLayout(new BorderLayout());
+
+        {
+            groupId = new JTextField(25);
+            artifactId = new JTextField(25);
+            version = new JTextField(25);
+
+            CellConstraints cc = new CellConstraints();
+            PanelBuilder builder = new PanelBuilder(
+                    new FormLayout(
+                            "right:max(50dlu;pref), 3dlu, 
fill:min(100dlu;pref)",
+                            "p, 3dlu, p, 3dlu, p, 3dlu"
+                    ));
+            builder.setDefaultDialogBorder();
+
+            builder.addLabel("group id:", cc.xy(1, 1));
+            builder.add(groupId, cc.xy(3, 1));
+
+            builder.addLabel("artifact id:", cc.xy(1, 3));
+            builder.add(artifactId, cc.xy(3, 3));
+
+            builder.addLabel("version:", cc.xy(1, 5));
+            builder.add(version, cc.xy(3, 5));
+
+            getContentPane().add(builder.getPanel(), BorderLayout.NORTH);
+        }
+
+        {
+            downloadButton = new JButton("Download");
+            cancelButton = new JButton("Cancel");
+            getRootPane().setDefaultButton(downloadButton);
+
+            JButton[] buttons = {cancelButton, downloadButton};
+            getContentPane().add(PanelFactory.createButtonPanel(buttons), 
BorderLayout.SOUTH);
+        }
+    }
+
+    public void close() {
+        setVisible(false);
+        dispose();
+    }
+
+    public JButton getCancelButton() {
+        return cancelButton;
+    }
+
+    public JButton getDownloadButton() {
+        return downloadButton;
+    }
+
+    public JTextField getArtifactId() {
+        return artifactId;
+    }
+
+    public JTextField getGroupId() {
+        return groupId;
+    }
+
+    public JTextField getVersion() {
+        return version;
+    }
+}
\ No newline at end of file

Reply via email to