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