mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
UI: symbols download fixes:
* fixed that mana symbols don't refresh after download finisged (#5592, no more xmage restarts); * fixed that window don't close after download finished;
This commit is contained in:
parent
232d37ec9b
commit
9ef888c634
5 changed files with 223 additions and 201 deletions
|
@ -1,26 +1,9 @@
|
||||||
package org.mage.plugins.card;
|
package org.mage.plugins.card;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Frame;
|
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.JDialog;
|
|
||||||
import javax.swing.JLayeredPane;
|
|
||||||
import mage.cards.MagePermanent;
|
import mage.cards.MagePermanent;
|
||||||
import mage.cards.action.ActionCallback;
|
import mage.cards.action.ActionCallback;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.client.util.GUISizeHelper;
|
import mage.client.util.GUISizeHelper;
|
||||||
import mage.constants.Rarity;
|
|
||||||
import mage.interfaces.plugin.CardPlugin;
|
import mage.interfaces.plugin.CardPlugin;
|
||||||
import mage.view.CardView;
|
import mage.view.CardView;
|
||||||
import mage.view.CounterView;
|
import mage.view.CounterView;
|
||||||
|
@ -41,14 +24,21 @@ import org.mage.plugins.card.dl.sources.ScryfallSymbolsSource;
|
||||||
import org.mage.plugins.card.images.ImageCache;
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CardPlugin} implementation.
|
* {@link CardPlugin} implementation.
|
||||||
*
|
*
|
||||||
* @author nantuko
|
* @author nantuko, JayDi85
|
||||||
* @version 0.1 01.11.2010 Mage permanents. Sorting card layout.
|
|
||||||
* @version 0.6 17.07.2011 #sortPermanents got option to display non-land
|
|
||||||
* permanents in one pile
|
|
||||||
* @version 0.7 29.07.2011 face down cards support
|
|
||||||
*/
|
*/
|
||||||
@PluginImplementation
|
@PluginImplementation
|
||||||
@Author(name = "nantuko")
|
@Author(name = "nantuko")
|
||||||
|
@ -584,6 +574,10 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void symbolsOnFinish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download various symbols (mana, tap, set).
|
* Download various symbols (mana, tap, set).
|
||||||
*
|
*
|
||||||
|
@ -591,23 +585,25 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void downloadSymbols(String imagesDir) {
|
public void downloadSymbols(String imagesDir) {
|
||||||
final DownloadGui g = new DownloadGui(new Downloader());
|
final Downloader downloader = new Downloader();
|
||||||
|
final DownloadGui downloadGui = new DownloadGui(downloader);
|
||||||
|
|
||||||
Iterable<DownloadJob> it;
|
LOGGER.info("Symbols download prepare...");
|
||||||
|
Iterable<DownloadJob> jobs;
|
||||||
|
|
||||||
it = new GathererSymbols();
|
jobs = new GathererSymbols();
|
||||||
for (DownloadJob job : it) {
|
for (DownloadJob job : jobs) {
|
||||||
g.getDownloader().add(job);
|
downloader.add(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
it = new GathererSets();
|
jobs = new GathererSets();
|
||||||
for (DownloadJob job : it) {
|
for (DownloadJob job : jobs) {
|
||||||
g.getDownloader().add(job);
|
downloader.add(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
it = new ScryfallSymbolsSource();
|
jobs = new ScryfallSymbolsSource();
|
||||||
for (DownloadJob job : it) {
|
for (DownloadJob job : jobs) {
|
||||||
g.getDownloader().add(job);
|
downloader.add(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -615,26 +611,56 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
for (DownloadJob job : it) {
|
for (DownloadJob job : it) {
|
||||||
g.getDownloader().add(job);
|
g.getDownloader().add(job);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
it = new DirectLinksForDownload();
|
|
||||||
for (DownloadJob job : it) {
|
jobs = new DirectLinksForDownload();
|
||||||
g.getDownloader().add(job);
|
for (DownloadJob job : jobs) {
|
||||||
|
downloader.add(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
JDialog d = new JDialog((Frame) null, "Download symbols", false);
|
LOGGER.info("Symbols download needs " + downloader.getJobs().size() + " files");
|
||||||
d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
|
||||||
d.addWindowListener(new WindowAdapter() {
|
// download GUI dialog
|
||||||
|
JDialog dialog = new JDialog((Frame) null, "Download symbols", false);
|
||||||
|
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||||
|
dialog.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
g.getDownloader().dispose();
|
// user force to close window/downloader
|
||||||
ManaSymbols.loadImages();
|
downloader.cleanup();
|
||||||
// TODO: check reload process after download (icons do not update)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
d.setLayout(new BorderLayout());
|
dialog.setLayout(new BorderLayout());
|
||||||
d.add(g);
|
dialog.add(downloadGui);
|
||||||
d.pack();
|
dialog.pack();
|
||||||
d.setVisible(true);
|
dialog.setVisible(true);
|
||||||
|
|
||||||
|
// downloader controller thread
|
||||||
|
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
|
downloader.publishAllJobs();
|
||||||
|
downloader.waitFinished();
|
||||||
|
downloader.cleanup();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// downloader finisher
|
||||||
|
worker.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals("state")) {
|
||||||
|
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
|
||||||
|
// all done, can close dialog and refresh symbols for UI
|
||||||
|
LOGGER.info("Symbols download finished");
|
||||||
|
dialog.dispose();
|
||||||
|
ManaSymbols.loadImages();
|
||||||
|
ImageCache.clearCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
worker.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,113 +1,105 @@
|
||||||
/**
|
|
||||||
* DownloadGui.java
|
|
||||||
*
|
|
||||||
* Created on 25.08.2010
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.mage.plugins.card.dl;
|
package org.mage.plugins.card.dl;
|
||||||
|
|
||||||
|
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import javax.swing.*;
|
||||||
import java.awt.Dimension;
|
import java.awt.*;
|
||||||
import java.beans.IndexedPropertyChangeEvent;
|
import java.beans.IndexedPropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.BoundedRangeModel;
|
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.DefaultBoundedRangeModel;
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JProgressBar;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
|
|
||||||
import org.mage.plugins.card.dl.DownloadJob.State;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class DownloadGui.
|
* Downloader GUI to control and show progress
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
|
||||||
* @author Clemens Koza
|
* @author Clemens Koza
|
||||||
*/
|
*/
|
||||||
public class DownloadGui extends JPanel {
|
public class DownloadGui extends JPanel {
|
||||||
private static final long serialVersionUID = -7346572382493844327L;
|
private static final long serialVersionUID = -7346572382493844327L;
|
||||||
|
|
||||||
private final Downloader d;
|
private final Downloader downloader;
|
||||||
private final DownloadListener l = new DownloadListener();
|
private final DownloadListener listener = new DownloadListener();
|
||||||
private final BoundedRangeModel model = new DefaultBoundedRangeModel(0, 0, 0, 0);
|
private final BoundedRangeModel progressModel = new DefaultBoundedRangeModel(0, 0, 0, 0);
|
||||||
private final JProgressBar progress = new JProgressBar(model);
|
private final JProgressBar progressBar = new JProgressBar(progressModel);
|
||||||
|
|
||||||
private final Map<DownloadJob, DownloadPanel> progresses = new HashMap<>();
|
private final Map<DownloadJob, DownloadPanel> jobPanels = new HashMap<>();
|
||||||
private final JPanel panel = new JPanel();
|
private final JPanel basicPanel = new JPanel();
|
||||||
|
|
||||||
public DownloadGui(Downloader downloader) {
|
public DownloadGui(Downloader downloader) {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
this.d = downloader;
|
this.downloader = downloader;
|
||||||
downloader.addPropertyChangeListener(l);
|
downloader.addPropertyChangeListener(listener);
|
||||||
|
|
||||||
JPanel p = new JPanel(new BorderLayout());
|
JPanel p = new JPanel(new BorderLayout());
|
||||||
p.setBorder(BorderFactory.createTitledBorder("Progress:"));
|
p.setBorder(BorderFactory.createTitledBorder("Progress:"));
|
||||||
p.add(progress);
|
p.add(progressBar);
|
||||||
JButton b = new JButton("X");
|
JButton closeButton = new JButton("X");
|
||||||
b.addActionListener(e -> {
|
closeButton.addActionListener(e -> {
|
||||||
d.dispose();
|
this.downloader.cleanup();
|
||||||
});
|
});
|
||||||
p.add(b, BorderLayout.EAST);
|
p.add(closeButton, BorderLayout.EAST);
|
||||||
add(p, BorderLayout.NORTH);
|
add(p, BorderLayout.NORTH);
|
||||||
|
|
||||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
basicPanel.setLayout(new BoxLayout(basicPanel, BoxLayout.Y_AXIS));
|
||||||
JScrollPane pane = new JScrollPane(panel);
|
JScrollPane pane = new JScrollPane(basicPanel);
|
||||||
pane.setPreferredSize(new Dimension(500, 300));
|
pane.setPreferredSize(new Dimension(500, 300));
|
||||||
add(pane);
|
add(pane);
|
||||||
for(int i = 0; i < downloader.getJobs().size(); i++) {
|
for (int i = 0; i < downloader.getJobs().size(); i++) {
|
||||||
addJob(i, downloader.getJobs().get(i));
|
addJob(i, downloader.getJobs().get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Downloader getDownloader() {
|
public Downloader getDownloader() {
|
||||||
return d;
|
return downloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DownloadListener implements PropertyChangeListener {
|
private class DownloadListener implements PropertyChangeListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String name = evt.getPropertyName();
|
String name = evt.getPropertyName();
|
||||||
if(evt.getSource() instanceof DownloadJob) {
|
if (evt.getSource() instanceof DownloadJob) {
|
||||||
DownloadPanel p = progresses.get(evt.getSource());
|
// one job changes
|
||||||
|
DownloadPanel panel = jobPanels.get(evt.getSource());
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "state":
|
case "state":
|
||||||
if(evt.getOldValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
if (evt.getOldValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
||||||
|
// started
|
||||||
changeProgress(-1, 0);
|
changeProgress(-1, 0);
|
||||||
} if(evt.getNewValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
}
|
||||||
changeProgress(+1, 0);
|
if (evt.getNewValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
||||||
} if(p != null) {
|
// finished
|
||||||
p.setVisible(p.getJob().getState() != State.FINISHED);
|
changeProgress(+1, 0);
|
||||||
p.revalidate();
|
}
|
||||||
} break;
|
if (panel != null) {
|
||||||
|
panel.setVisible(panel.getJob().getState() != State.FINISHED);
|
||||||
|
panel.revalidate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "message":
|
case "message":
|
||||||
if(p != null) {
|
if (panel != null) {
|
||||||
JProgressBar bar = p.getBar();
|
JProgressBar bar = panel.getBar();
|
||||||
String message = p.getJob().getMessage();
|
String message = panel.getJob().getMessage();
|
||||||
bar.setStringPainted(message != null);
|
bar.setStringPainted(message != null);
|
||||||
bar.setString(message);
|
bar.setString(message);
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if(evt.getSource() == d) {
|
} else if (evt.getSource() == downloader) {
|
||||||
if("jobs".equals(name)) {
|
// all jobs changes (add/delete)
|
||||||
|
if ("jobs".equals(name)) {
|
||||||
IndexedPropertyChangeEvent ev = (IndexedPropertyChangeEvent) evt;
|
IndexedPropertyChangeEvent ev = (IndexedPropertyChangeEvent) evt;
|
||||||
int index = ev.getIndex();
|
int index = ev.getIndex();
|
||||||
|
|
||||||
DownloadJob oldValue = (DownloadJob) ev.getOldValue();
|
DownloadJob oldValue = (DownloadJob) ev.getOldValue();
|
||||||
if(oldValue != null) {
|
if (oldValue != null) {
|
||||||
removeJob(index, oldValue);
|
removeJob(index, oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadJob newValue = (DownloadJob) ev.getNewValue();
|
DownloadJob newValue = (DownloadJob) ev.getNewValue();
|
||||||
if(newValue != null) {
|
if (newValue != null) {
|
||||||
addJob(index, newValue);
|
addJob(index, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,39 +108,39 @@ public class DownloadGui extends JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void addJob(int index, DownloadJob job) {
|
private synchronized void addJob(int index, DownloadJob job) {
|
||||||
job.addPropertyChangeListener(l);
|
job.addPropertyChangeListener(listener);
|
||||||
changeProgress(0, +1);
|
changeProgress(0, +1);
|
||||||
DownloadPanel p = new DownloadPanel(job);
|
DownloadPanel p = new DownloadPanel(job);
|
||||||
progresses.put(job, p);
|
jobPanels.put(job, p);
|
||||||
panel.add(p, index);
|
basicPanel.add(p, index);
|
||||||
panel.revalidate();
|
basicPanel.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void removeJob(int index, DownloadJob job) {
|
private synchronized void removeJob(int index, DownloadJob job) {
|
||||||
assert progresses.get(job) == panel.getComponent(index);
|
assert jobPanels.get(job) == basicPanel.getComponent(index);
|
||||||
job.removePropertyChangeListener(l);
|
job.removePropertyChangeListener(listener);
|
||||||
changeProgress(0, -1);
|
changeProgress(0, -1);
|
||||||
progresses.remove(job);
|
jobPanels.remove(job);
|
||||||
panel.remove(index);
|
basicPanel.remove(index);
|
||||||
panel.revalidate();
|
basicPanel.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void changeProgress(int progress, int total) {
|
private synchronized void changeProgress(int progress, int total) {
|
||||||
progress += model.getValue();
|
progress += progressModel.getValue();
|
||||||
total += model.getMaximum();
|
total += progressModel.getMaximum();
|
||||||
model.setMaximum(total);
|
progressModel.setMaximum(total);
|
||||||
model.setValue(progress);
|
progressModel.setValue(progress);
|
||||||
this.progress.setStringPainted(true);
|
this.progressBar.setStringPainted(true);
|
||||||
this.progress.setString(progress + "/" + total);
|
this.progressBar.setString(progress + "/" + total);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DownloadPanel extends JPanel {
|
private class DownloadPanel extends JPanel {
|
||||||
private static final long serialVersionUID = 1187986738303477168L;
|
private static final long serialVersionUID = 1187986738303477168L;
|
||||||
|
|
||||||
private final DownloadJob job;
|
private final DownloadJob job;
|
||||||
private final JProgressBar bar;
|
private final JProgressBar bar;
|
||||||
|
|
||||||
public DownloadPanel(DownloadJob job) {
|
DownloadPanel(DownloadJob job) {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
this.job = job;
|
this.job = job;
|
||||||
|
|
||||||
|
@ -156,7 +148,7 @@ public class DownloadGui extends JPanel {
|
||||||
add(bar = new JProgressBar(job.getProgress()));
|
add(bar = new JProgressBar(job.getProgress()));
|
||||||
JButton b = new JButton("X");
|
JButton b = new JButton("X");
|
||||||
b.addActionListener(e -> {
|
b.addActionListener(e -> {
|
||||||
switch(this.job.getState()) {
|
switch (this.job.getState()) {
|
||||||
case NEW:
|
case NEW:
|
||||||
case PREPARING:
|
case PREPARING:
|
||||||
case WORKING:
|
case WORKING:
|
||||||
|
@ -165,7 +157,7 @@ public class DownloadGui extends JPanel {
|
||||||
});
|
});
|
||||||
add(b, BorderLayout.EAST);
|
add(b, BorderLayout.EAST);
|
||||||
|
|
||||||
if(job.getState() == State.FINISHED | job.getState() == State.ABORTED) {
|
if (job.getState() == State.FINISHED | job.getState() == State.ABORTED) {
|
||||||
changeProgress(+1, 0);
|
changeProgress(+1, 0);
|
||||||
}
|
}
|
||||||
setVisible(job.getState() != State.FINISHED);
|
setVisible(job.getState() != State.FINISHED);
|
||||||
|
@ -177,15 +169,13 @@ public class DownloadGui extends JPanel {
|
||||||
Dimension d = getPreferredSize();
|
Dimension d = getPreferredSize();
|
||||||
d.width = Integer.MAX_VALUE;
|
d.width = Integer.MAX_VALUE;
|
||||||
setMaximumSize(d);
|
setMaximumSize(d);
|
||||||
// d.width = 500;
|
|
||||||
// setMinimumSize(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadJob getJob() {
|
DownloadJob getJob() {
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JProgressBar getBar() {
|
JProgressBar getBar() {
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
/**
|
|
||||||
* DownloadJob.java
|
|
||||||
*
|
|
||||||
* Created on 25.08.2010
|
|
||||||
*/
|
|
||||||
package org.mage.plugins.card.dl;
|
package org.mage.plugins.card.dl;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import javax.swing.BoundedRangeModel;
|
|
||||||
import javax.swing.DefaultBoundedRangeModel;
|
|
||||||
import org.mage.plugins.card.dl.beans.properties.Property;
|
import org.mage.plugins.card.dl.beans.properties.Property;
|
||||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||||
import org.mage.plugins.card.utils.CardImageUtils;
|
import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class DownloadJob.
|
* Downloader job to download one resource
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
|
||||||
* @author Clemens Koza, JayDi85
|
* @author Clemens Koza, JayDi85
|
||||||
*/
|
*/
|
||||||
public class DownloadJob extends AbstractLaternaBean {
|
public class DownloadJob extends AbstractLaternaBean {
|
||||||
|
@ -88,11 +78,8 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
*/
|
*/
|
||||||
public void setError(String message, Exception error) {
|
public void setError(String message, Exception error) {
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
|
message = "Download of " + name + " from " + source.toString() + " caused error: " + error.toString();
|
||||||
message = "Download of " + name + "from " + source.toString() + " caused error: " + error.toString();
|
|
||||||
}
|
}
|
||||||
// log.warn(message, error);
|
|
||||||
log.warn(message);
|
|
||||||
this.state.setValue(State.ABORTED);
|
this.state.setValue(State.ABORTED);
|
||||||
this.error.setValue(error);
|
this.error.setValue(error);
|
||||||
this.message.setValue(message);
|
this.message.setValue(message);
|
||||||
|
@ -116,7 +103,7 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// change to working state on good prepare call
|
// can continue
|
||||||
this.state.setValue(State.WORKING);
|
this.state.setValue(State.WORKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,9 @@
|
||||||
/**
|
|
||||||
* Downloader.java
|
|
||||||
*
|
|
||||||
* Created on 25.08.2010
|
|
||||||
*/
|
|
||||||
package org.mage.plugins.card.dl;
|
package org.mage.plugins.card.dl;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.ConnectException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import javax.swing.BoundedRangeModel;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jetlang.channels.Channel;
|
import org.jetlang.channels.Channel;
|
||||||
import org.jetlang.channels.MemoryChannel;
|
import org.jetlang.channels.MemoryChannel;
|
||||||
import org.jetlang.core.Callback;
|
import org.jetlang.core.Callback;
|
||||||
import org.jetlang.core.Disposable;
|
|
||||||
import org.jetlang.fibers.Fiber;
|
import org.jetlang.fibers.Fiber;
|
||||||
import org.jetlang.fibers.PoolFiberFactory;
|
import org.jetlang.fibers.PoolFiberFactory;
|
||||||
import org.mage.plugins.card.dl.DownloadJob.Destination;
|
import org.mage.plugins.card.dl.DownloadJob.Destination;
|
||||||
|
@ -28,41 +11,56 @@ import org.mage.plugins.card.dl.DownloadJob.Source;
|
||||||
import org.mage.plugins.card.dl.DownloadJob.State;
|
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class Downloader.
|
* Downloader
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
* @author Clemens Koza, JayDi85
|
||||||
* @author Clemens Koza
|
|
||||||
*/
|
*/
|
||||||
public class Downloader extends AbstractLaternaBean implements Disposable {
|
public class Downloader extends AbstractLaternaBean {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Downloader.class);
|
private static final Logger logger = Logger.getLogger(Downloader.class);
|
||||||
|
|
||||||
private final List<DownloadJob> jobs = properties.list("jobs");
|
private final List<DownloadJob> jobs = properties.list("jobs");
|
||||||
private final Channel<DownloadJob> channel = new MemoryChannel<>();
|
private final Channel<DownloadJob> jobsQueue = new MemoryChannel<>();
|
||||||
|
private CountDownLatch worksCount = null;
|
||||||
|
|
||||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||||
private final List<Fiber> fibers = new ArrayList<>();
|
private final List<Fiber> fibers = new ArrayList<>();
|
||||||
|
|
||||||
public Downloader() {
|
public Downloader() {
|
||||||
|
// prepare 10 threads and start to waiting new download jobs from queue
|
||||||
PoolFiberFactory f = new PoolFiberFactory(pool);
|
PoolFiberFactory f = new PoolFiberFactory(pool);
|
||||||
//subscribe multiple fibers for parallel execution
|
|
||||||
for (int i = 0, numThreads = 10; i < numThreads; i++) {
|
for (int i = 0, numThreads = 10; i < numThreads; i++) {
|
||||||
Fiber fiber = f.create();
|
Fiber fiber = f.create();
|
||||||
fiber.start();
|
fiber.start();
|
||||||
fibers.add(fiber);
|
fibers.add(fiber);
|
||||||
channel.subscribe(fiber, new DownloadCallback());
|
jobsQueue.subscribe(fiber, new DownloadCallback());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void cleanup() {
|
||||||
public void dispose() {
|
// close all threads and jobs
|
||||||
for (DownloadJob j : jobs) {
|
for (DownloadJob j : jobs) {
|
||||||
switch (j.getState()) {
|
switch (j.getState()) {
|
||||||
case NEW:
|
case NEW:
|
||||||
case PREPARING:
|
case PREPARING:
|
||||||
case WORKING:
|
case WORKING:
|
||||||
j.setState(State.ABORTED);
|
j.setState(State.ABORTED);
|
||||||
|
break;
|
||||||
|
case ABORTED:
|
||||||
|
case FINISHED:
|
||||||
|
// don't change state
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,16 +68,10 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
f.dispose();
|
f.dispose();
|
||||||
}
|
}
|
||||||
pool.shutdown();
|
pool.shutdown();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
while (worksCount.getCount() != 0) {
|
||||||
*
|
worksCount.countDown();
|
||||||
* @throws Throwable
|
}
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
dispose();
|
|
||||||
super.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(DownloadJob job) {
|
public void add(DownloadJob job) {
|
||||||
|
@ -94,7 +86,27 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
}
|
}
|
||||||
job.setState(State.NEW);
|
job.setState(State.NEW);
|
||||||
jobs.add(job);
|
jobs.add(job);
|
||||||
channel.publish(job);
|
}
|
||||||
|
|
||||||
|
public void publishAllJobs() {
|
||||||
|
worksCount = new CountDownLatch(jobs.size());
|
||||||
|
for (DownloadJob job : jobs) {
|
||||||
|
jobsQueue.publish(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitFinished() {
|
||||||
|
try {
|
||||||
|
while (worksCount.getCount() != 0) {
|
||||||
|
worksCount.await(60, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
if (worksCount.getCount() != 0) {
|
||||||
|
logger.warn("Symbols download too long...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("Need to stop symbols download...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadJob> getJobs() {
|
public List<DownloadJob> getJobs() {
|
||||||
|
@ -111,20 +123,23 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(DownloadJob job) {
|
public void onMessage(DownloadJob job) {
|
||||||
|
|
||||||
// start to work
|
// each 10 threads gets same jobs, but take to work only one NEW
|
||||||
// the job won't be processed by multiple threads
|
|
||||||
synchronized (job) {
|
synchronized (job) {
|
||||||
if (job.getState() != State.NEW) {
|
if (job.getState() == State.NEW) {
|
||||||
return;
|
// take new job
|
||||||
}
|
job.doPrepareAndStartWork();
|
||||||
|
if (job.getState() != State.WORKING) {
|
||||||
job.doPrepareAndStartWork();
|
logger.warn("Can't prepare symbols download job: " + job.getName());
|
||||||
|
worksCount.countDown();
|
||||||
if (job.getState() != State.WORKING) {
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// skip job (other thread takes it)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// real work for new job
|
||||||
// download and save data
|
// download and save data
|
||||||
try {
|
try {
|
||||||
Source src = job.getSource();
|
Source src = job.getSource();
|
||||||
|
@ -132,9 +147,11 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
BoundedRangeModel progress = job.getProgress();
|
BoundedRangeModel progress = job.getProgress();
|
||||||
|
|
||||||
if (dst.isValid()) {
|
if (dst.isValid()) {
|
||||||
|
// already done
|
||||||
progress.setMaximum(1);
|
progress.setMaximum(1);
|
||||||
progress.setValue(1);
|
progress.setValue(1);
|
||||||
} else {
|
} else {
|
||||||
|
// downloading
|
||||||
if (dst.exists()) {
|
if (dst.exists()) {
|
||||||
try {
|
try {
|
||||||
dst.delete();
|
dst.delete();
|
||||||
|
@ -149,7 +166,7 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
try {
|
try {
|
||||||
byte[] buf = new byte[8 * 1024];
|
byte[] buf = new byte[8 * 1024];
|
||||||
int total = 0;
|
int total = 0;
|
||||||
for (int len; (len = is.read(buf)) != -1;) {
|
for (int len; (len = is.read(buf)) != -1; ) {
|
||||||
if (job.getState() == State.ABORTED) {
|
if (job.getState() == State.ABORTED) {
|
||||||
throw new IOException("Job was aborted");
|
throw new IOException("Job was aborted");
|
||||||
}
|
}
|
||||||
|
@ -193,6 +210,8 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
logger.warn("Error resource download " + job.getName() + " from " + job.getSource().toString() + ": " + message);
|
logger.warn("Error resource download " + job.getName() + " from " + job.getSource().toString() + ": " + message);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
job.setError(ex);
|
job.setError(ex);
|
||||||
|
} finally {
|
||||||
|
worksCount.countDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* AbstractLaternaBean.java
|
* AbstractLaternaBean.java
|
||||||
*
|
* <p>
|
||||||
* Created on 25.08.2010
|
* Created on 25.08.2010
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ import org.mage.plugins.card.dl.beans.properties.bound.BoundProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class AbstractLaternaBean.
|
* The class AbstractLaternaBean.
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
|
||||||
* @author Clemens Koza
|
* @author Clemens Koza
|
||||||
|
* @version V0.0 25.08.2010
|
||||||
*/
|
*/
|
||||||
public class AbstractLaternaBean extends AbstractBoundBean {
|
public class AbstractLaternaBean extends AbstractBoundBean {
|
||||||
protected static final Logger log = Logger.getLogger(AbstractLaternaBean.class);
|
protected static final Logger log = Logger.getLogger(AbstractLaternaBean.class);
|
||||||
protected final Properties properties = new BoundProperties(s);
|
protected final Properties properties = new BoundProperties(s);
|
||||||
protected EventListenerList listeners = new EventListenerList();
|
protected EventListenerList listeners = new EventListenerList();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue