diff --git a/lib/glazedlists.jar b/lib/glazedlists.jar index 38fb8c17..14537477 100644 Binary files a/lib/glazedlists.jar and b/lib/glazedlists.jar differ diff --git a/source/net/sourceforge/filebot/Settings.java b/source/net/sourceforge/filebot/Settings.java index b7e34316..6fe5fdaa 100644 --- a/source/net/sourceforge/filebot/Settings.java +++ b/source/net/sourceforge/filebot/Settings.java @@ -7,7 +7,7 @@ import java.util.Map; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; import net.sourceforge.tuned.PreferencesList; import net.sourceforge.tuned.PreferencesMap; import net.sourceforge.tuned.PreferencesMap.Adapter; @@ -96,7 +96,7 @@ public final class Settings { // remove entries prefs.clear(); } catch (BackingStoreException e) { - throw ExceptionUtil.asRuntimeException(e); + throw ExceptionUtilities.asRuntimeException(e); } } } diff --git a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java index 33243952..6495af87 100644 --- a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java +++ b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java @@ -30,7 +30,7 @@ import javax.swing.SwingWorker; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.web.SearchResult; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; import net.sourceforge.tuned.ui.LabelProvider; import net.sourceforge.tuned.ui.SelectButtonTextField; import net.sourceforge.tuned.ui.TunedUtilities; @@ -184,7 +184,7 @@ public abstract class AbstractSearchPanel extends FileBotPanel { } catch (Exception e) { tab.close(); - Logger.getLogger("ui").log(Level.WARNING, ExceptionUtil.getRootCause(e).getMessage(), e); + Logger.getLogger("ui").log(Level.WARNING, ExceptionUtilities.getRootCause(e).getMessage(), e); } } @@ -240,7 +240,7 @@ public abstract class AbstractSearchPanel extends FileBotPanel { } catch (Exception e) { tab.close(); - Logger.getLogger("ui").log(Level.WARNING, ExceptionUtil.getRootCause(e).getMessage(), e); + Logger.getLogger("ui").log(Level.WARNING, ExceptionUtilities.getRootCause(e).getMessage(), e); } finally { tab.setLoading(false); } diff --git a/source/net/sourceforge/filebot/ui/FileBotListExportHandler.java b/source/net/sourceforge/filebot/ui/FileBotListExportHandler.java index b5ef99a4..bdfc94bc 100644 --- a/source/net/sourceforge/filebot/ui/FileBotListExportHandler.java +++ b/source/net/sourceforge/filebot/ui/FileBotListExportHandler.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui; -import java.io.PrintWriter; +import java.util.Formatter; import net.sourceforge.filebot.ui.transfer.TextFileExportHandler; @@ -24,9 +24,9 @@ public class FileBotListExportHandler extends TextFileExportHandler { @Override - public void export(PrintWriter out) { + public void export(Formatter out) { for (Object entry : list.getModel()) { - out.println(entry); + out.format("%s%n", entry); } } diff --git a/source/net/sourceforge/filebot/ui/panel/analyze/Tool.java b/source/net/sourceforge/filebot/ui/panel/analyze/Tool.java index 0b6e1441..30223b46 100644 --- a/source/net/sourceforge/filebot/ui/panel/analyze/Tool.java +++ b/source/net/sourceforge/filebot/ui/panel/analyze/Tool.java @@ -16,7 +16,7 @@ import javax.swing.SwingWorker; import net.sourceforge.filebot.ui.panel.analyze.FileTree.FileNode; import net.sourceforge.filebot.ui.panel.analyze.FileTree.FolderNode; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; import net.sourceforge.tuned.FileUtilities; import net.sourceforge.tuned.ui.TunedUtilities; @@ -90,7 +90,7 @@ abstract class Tool extends JComponent { try { setModel(get()); } catch (Exception e) { - if (ExceptionUtil.getRootCause(e) instanceof ConcurrentModificationException) { + if (ExceptionUtilities.getRootCause(e) instanceof ConcurrentModificationException) { // if it happens, it is supposed to } else { // should not happen diff --git a/source/net/sourceforge/filebot/ui/panel/rename/AutoFetchEpisodeListMatcher.java b/source/net/sourceforge/filebot/ui/panel/rename/AutoFetchEpisodeListMatcher.java index c6b4590e..e3fc26f9 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/AutoFetchEpisodeListMatcher.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/AutoFetchEpisodeListMatcher.java @@ -49,14 +49,19 @@ class AutoFetchEpisodeListMatcher extends SwingWorker> } - public Collection remainingFiles() { - return Collections.unmodifiableCollection(files); + public List remainingFiles() { + return Collections.unmodifiableList(files); } protected Collection detectSeriesNames(Collection files) { // detect series name(s) from files - return new SeriesNameMatcher().matchAll(files.toArray(new File[0])); + Collection names = new SeriesNameMatcher().matchAll(files.toArray(new File[0])); + + if (names.isEmpty()) + throw new IllegalArgumentException("Cannot auto-detect series name."); + + return names; } @@ -79,9 +84,6 @@ class AutoFetchEpisodeListMatcher extends SwingWorker> }); } - if (tasks.isEmpty()) - throw new IllegalArgumentException("Failed to auto-detect series name."); - // fetch episode lists concurrently List episodes = new ArrayList(); ExecutorService executor = Executors.newFixedThreadPool(tasks.size()); diff --git a/source/net/sourceforge/filebot/ui/panel/rename/RenameModel.java b/source/net/sourceforge/filebot/ui/panel/rename/RenameModel.java index 38a103ee..15f13d73 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/RenameModel.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/RenameModel.java @@ -8,13 +8,12 @@ import java.util.Collection; import net.sourceforge.filebot.similarity.Match; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; -import ca.odell.glazedlists.GlazedLists; class RenameModel { - private final EventList names = GlazedLists.threadSafeList(new BasicEventList()); - private final EventList files = GlazedLists.threadSafeList(new BasicEventList()); + private final EventList names = new BasicEventList(); + private final EventList files = new BasicEventList(); public EventList names() { diff --git a/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java b/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java index d1940922..79e30fb4 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java @@ -31,7 +31,7 @@ import net.sourceforge.filebot.web.Episode; import net.sourceforge.filebot.web.EpisodeListClient; import net.sourceforge.filebot.web.TVRageClient; import net.sourceforge.filebot.web.TheTVDBClient; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; import net.sourceforge.tuned.ui.ActionPopup; import net.sourceforge.tuned.ui.LoadingOverlayPane; import ca.odell.glazedlists.event.ListEvent; @@ -215,7 +215,7 @@ public class RenamePanel extends FileBotPanel { model.names().addAll(names); model.files().addAll(files); } catch (Exception e) { - Logger.getLogger("ui").log(Level.WARNING, ExceptionUtil.getRootCause(e).getMessage(), e); + Logger.getLogger("ui").log(Level.WARNING, ExceptionUtilities.getRootCause(e).getMessage(), e); } } }; diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/Checksum.java b/source/net/sourceforge/filebot/ui/panel/sfv/Checksum.java deleted file mode 100644 index fca74540..00000000 --- a/source/net/sourceforge/filebot/ui/panel/sfv/Checksum.java +++ /dev/null @@ -1,168 +0,0 @@ - -package net.sourceforge.filebot.ui.panel.sfv; - - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.logging.Level; -import java.util.logging.Logger; - -import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; - - -public class Checksum { - - private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - - public static final String STATE_PROPERTY = "state"; - public static final String PROGRESS_PROPERTY = "progress"; - - private Long checksum = null; - private State state = State.PENDING; - private ChecksumComputationTask computationTask = null; - private String errorMessage = null; - - - public static enum State { - PENDING, - INPROGRESS, - READY, - ERROR; - } - - - public Checksum(long checksum) { - setChecksum(checksum); - setState(State.READY); - } - - - public Checksum(String checksumString) { - this(Long.parseLong(checksumString, 16)); - } - - - protected Checksum(ChecksumComputationTask computationTask) { - this.computationTask = computationTask; - this.computationTask.addPropertyChangeListener(new ComputationTaskPropertyChangeListener()); - } - - - public String getChecksumString() { - return String.format("%08x", checksum).toUpperCase(); - } - - - public Long getChecksum() { - return checksum; - } - - - public synchronized void setChecksum(Long checksum) { - this.checksum = checksum; - setState(State.READY); - - computationTask = null; - } - - - public synchronized void setChecksumError(Exception exception) { - // get root cause - Throwable cause = exception; - - while (cause.getCause() != null) - cause = cause.getCause(); - - errorMessage = cause.getMessage(); - setState(State.ERROR); - - computationTask = null; - } - - - public State getState() { - return state; - } - - - private void setState(State state) { - this.state = state; - propertyChangeSupport.firePropertyChange(STATE_PROPERTY, null, state); - } - - - public synchronized Integer getProgress() { - if (state == State.INPROGRESS) - return computationTask.getProgress(); - - return null; - } - - - public String getErrorMessage() { - return errorMessage; - } - - - public synchronized void cancelComputationTask() { - if (computationTask == null) - return; - - computationTask.cancel(false); - } - - - private class ComputationTaskPropertyChangeListener extends SwingWorkerPropertyChangeAdapter { - - @Override - public void progress(PropertyChangeEvent evt) { - propertyChangeSupport.firePropertyChange(PROGRESS_PROPERTY, null, evt.getNewValue()); - } - - - @Override - public void started(PropertyChangeEvent evt) { - setState(State.INPROGRESS); - } - - - @Override - public void done(PropertyChangeEvent evt) { - try { - ChecksumComputationTask task = (ChecksumComputationTask) evt.getSource(); - - if (!task.isCancelled()) { - setChecksum(task.get()); - } - } catch (Exception e) { - // might happen if file system is corrupt (e.g. CRC errors) - setChecksumError(e); - Logger.getLogger("global").log(Level.WARNING, e.getMessage()); - } - } - } - - - public void addPropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(listener); - } - - - public void removePropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.removePropertyChangeListener(listener); - } - - - @Override - public String toString() { - if (state == State.READY) - return getChecksumString(); - - if (state == State.ERROR) - return getErrorMessage(); - - return state.toString(); - } - -} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumCell.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumCell.java new file mode 100644 index 00000000..ab883bb3 --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumCell.java @@ -0,0 +1,141 @@ + +package net.sourceforge.filebot.ui.panel.sfv; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.util.Map; + +import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; + + +public class ChecksumCell { + + private final String name; + private final File root; + + private Map hashes; + private ChecksumComputationTask task; + private Throwable error; + + + public static enum State { + PENDING, + PROGRESS, + READY, + ERROR + } + + + public ChecksumCell(String name, File root, Map hashes) { + this.name = name; + this.root = root; + this.hashes = hashes; + } + + + public ChecksumCell(String name, File root, ChecksumComputationTask computationTask) { + this.name = name; + this.root = root; + this.task = computationTask; + + // forward property change events + task.addPropertyChangeListener(new SwingWorkerPropertyChangeAdapter() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + super.propertyChange(evt); + + propertyChangeSupport.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + + + @Override + protected void done(PropertyChangeEvent evt) { + try { + hashes = task.get(); + } catch (Exception e) { + error = ExceptionUtilities.getRootCause(e); + } finally { + task = null; + } + } + }); + } + + + public String getName() { + return name; + } + + + public File getRoot() { + return root; + } + + + public String getChecksum(HashType type) { + if (hashes != null) + return hashes.get(type); + + return null; + } + + + public ChecksumComputationTask getTask() { + return task; + } + + + public Throwable getError() { + return error; + } + + + public void dispose() { + if (task != null) { + task.cancel(true); + } + + hashes = null; + error = null; + task = null; + } + + + public State getState() { + if (hashes != null) + return State.READY; + if (error != null) + return State.ERROR; + + switch (task.getState()) { + case PENDING: + return State.PENDING; + default: + return State.PROGRESS; + } + } + + + @Override + public String toString() { + return String.format("%s %s", name, hashes); + } + + private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(listener); + } + +} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationService.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationService.java index d686ddda..01183aa3 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationService.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationService.java @@ -2,194 +2,130 @@ package net.sourceforge.filebot.ui.panel.sfv; -import java.beans.PropertyChangeEvent; +import static java.lang.Math.log10; +import static java.lang.Math.max; + import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; -import java.io.File; import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.SwingUtilities; import net.sourceforge.tuned.DefaultThreadFactory; public class ChecksumComputationService { - public static final String ACTIVE_PROPERTY = "active"; - public static final String REMAINING_TASK_COUNT_PROPERTY = "remainingTaskCount"; + public static final String TASK_COUNT_PROPERTY = "taskCount"; - private final Map executors = new HashMap(); + private final List executors = new ArrayList(); - private final AtomicInteger activeSessionTaskCount = new AtomicInteger(0); - private final AtomicInteger remainingTaskCount = new AtomicInteger(0); - - private final ThreadFactory threadFactory; - - /** - * Property change events will be fired on the event dispatch thread - */ - private final SwingWorkerPropertyChangeSupport propertyChangeSupport = new SwingWorkerPropertyChangeSupport(this); + private final AtomicInteger completedTaskCount = new AtomicInteger(0); + private final AtomicInteger totalTaskCount = new AtomicInteger(0); - public ChecksumComputationService() { - this(new DefaultThreadFactory("ChecksumComputationPool", Thread.MIN_PRIORITY)); - } - - - public ChecksumComputationService(ThreadFactory threadFactory) { - this.threadFactory = threadFactory; - } - - - public Checksum schedule(File file, File workerQueue) { - ChecksumComputationTask task = new ChecksumComputationTask(file); - Checksum checksum = new Checksum(task); - - getExecutor(workerQueue).execute(task); - - return checksum; + public ExecutorService newExecutor() { + return new ChecksumComputationExecutor(); } public void reset() { - deactivate(true); - } - - - private synchronized void deactivate(boolean shutdownNow) { - for (ChecksumComputationExecutor executor : executors.values()) { - if (shutdownNow) + synchronized (executors) { + for (ExecutorService executor : executors) { executor.shutdownNow(); - else - executor.shutdown(); + } + + totalTaskCount.set(0); + completedTaskCount.set(0); + + executors.clear(); } - executors.clear(); - - activeSessionTaskCount.set(0); - remainingTaskCount.set(0); + fireTaskCountChanged(); } - public boolean isActive() { - return activeSessionTaskCount.get() > 0; + public int getTaskCount() { + return getTotalTaskCount() - getCompletedTaskCount(); } - public int getRemainingTaskCount() { - return remainingTaskCount.get(); + public int getTotalTaskCount() { + return totalTaskCount.get(); } - public int getActiveSessionTaskCount() { - return activeSessionTaskCount.get(); + public int getCompletedTaskCount() { + return completedTaskCount.get(); } - public synchronized void purge() { - for (ChecksumComputationExecutor executor : executors.values()) { - executor.purge(); + public void purge() { + synchronized (executors) { + for (ThreadPoolExecutor executor : executors) { + executor.purge(); + } } } - - private synchronized ChecksumComputationExecutor getExecutor(File workerQueue) { - ChecksumComputationExecutor executor = executors.get(workerQueue); - - if (executor == null) { - executor = new ChecksumComputationExecutor(); - executors.put(workerQueue, executor); - } - - return executor; - } - private class ChecksumComputationExecutor extends ThreadPoolExecutor { - private static final int MINIMUM_POOL_SIZE = 1; - - public ChecksumComputationExecutor() { - super(MINIMUM_POOL_SIZE, MINIMUM_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), threadFactory); + super(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue(), new DefaultThreadFactory("ChecksumComputationPool", Thread.MIN_PRIORITY)); + + synchronized (executors) { + executors.add(this); + } + + prestartAllCoreThreads(); } - private void adjustPoolSize() { + protected int getPreferredPoolSize() { // for a few files, use one thread // for lots of files, use multiple threads - // e.g 50 files ~ 1 thread, 1000 files ~ 3 threads, 40000 files ~ 5 threads - int preferredPoolSize = (int) Math.max(Math.log10(getQueue().size() / 10), MINIMUM_POOL_SIZE); - - if (getCorePoolSize() != preferredPoolSize) { - setCorePoolSize(preferredPoolSize); - } + // e.g 50 files ~ 1 thread, 200 files ~ 2 threads, 1000 files ~ 3 threads, 40000 files ~ 5 threads + return max((int) log10(getQueue().size()), 1); } @Override public void execute(Runnable command) { - if (activeSessionTaskCount.getAndIncrement() <= 0) { - setActive(true); + int preferredPoolSize = getPreferredPoolSize(); + + if (getCorePoolSize() < preferredPoolSize) { + setCorePoolSize(preferredPoolSize); } - super.execute(command); + synchronized (this) { + super.execute(command); + } - adjustPoolSize(); - - remainingTaskCount.incrementAndGet(); - fireRemainingTaskCountChange(); + totalTaskCount.incrementAndGet(); + fireTaskCountChanged(); } @Override public void purge() { - try { - List cancelledTasks = new ArrayList(); - - for (Runnable entry : getQueue()) { - ChecksumComputationTask task = (ChecksumComputationTask) entry; - - if (task.isCancelled()) { - cancelledTasks.add(task); - } - } - - for (ChecksumComputationTask task : cancelledTasks) { - remove(task); - } - } catch (ConcurrentModificationException e) { - Logger.getLogger("global").log(Level.SEVERE, e.toString(), e); - } - } - - - @Override - public boolean remove(Runnable task) { - boolean success = super.remove(task); + int delta = 0; - if (success) { - activeSessionTaskCount.decrementAndGet(); - - if (remainingTaskCount.decrementAndGet() <= 0) { - setActive(false); - } - - fireRemainingTaskCountChange(); + synchronized (this) { + delta += getQueue().size(); + super.purge(); + delta -= getQueue().size(); } - return success; + if (delta > 0) { + // subtract removed tasks from task count + totalTaskCount.addAndGet(-delta); + fireTaskCountChanged(); + } } @@ -197,54 +133,35 @@ public class ChecksumComputationService { protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); - if (remainingTaskCount.decrementAndGet() <= 0) { - deactivate(false); - setActive(false); - } - - fireRemainingTaskCountChange(); - } - } - - - private void setActive(boolean active) { - propertyChangeSupport.firePropertyChange(ACTIVE_PROPERTY, null, active); - } - - - private void fireRemainingTaskCountChange() { - propertyChangeSupport.firePropertyChange(REMAINING_TASK_COUNT_PROPERTY, null, getRemainingTaskCount()); - } - - - public void addPropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(listener); - } - - - public void removePropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.removePropertyChangeListener(listener); - } - - - private static class SwingWorkerPropertyChangeSupport extends PropertyChangeSupport { - - public SwingWorkerPropertyChangeSupport(Object sourceBean) { - super(sourceBean); + completedTaskCount.incrementAndGet(); + fireTaskCountChanged(); } @Override - public void firePropertyChange(final PropertyChangeEvent evt) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - SwingWorkerPropertyChangeSupport.super.firePropertyChange(evt); - } - - }); + protected void terminated() { + synchronized (executors) { + executors.remove(this); + } } + + } + + private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + + + private void fireTaskCountChanged() { + propertyChangeSupport.firePropertyChange(TASK_COUNT_PROPERTY, null, getTaskCount()); + } + + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(propertyName, listener); + } + + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(propertyName, listener); } } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationTask.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationTask.java index dbf4359b..fdde6adf 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationTask.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumComputationTask.java @@ -4,13 +4,14 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.io.File; import java.io.FileInputStream; -import java.util.zip.CRC32; -import java.util.zip.CheckedInputStream; - +import java.io.InputStream; +import java.util.EnumMap; +import java.util.Map; +import java.util.Map.Entry; import javax.swing.SwingWorker; -public class ChecksumComputationTask extends SwingWorker { +class ChecksumComputationTask extends SwingWorker, Void> { private static final int BUFFER_SIZE = 32 * 1024; @@ -23,37 +24,56 @@ public class ChecksumComputationTask extends SwingWorker { @Override - protected Long doInBackground() throws Exception { - CheckedInputStream cis = new CheckedInputStream(new FileInputStream(file), new CRC32()); + protected Map doInBackground() throws Exception { + Map hashes = new EnumMap(HashType.class); + + for (HashType type : HashType.values()) { + hashes.put(type, type.newInstance()); + } long length = file.length(); if (length > 0) { - long done = 0; + InputStream in = new FileInputStream(file); - byte[] buffer = new byte[BUFFER_SIZE]; - - int bytesRead = 0; - - while ((bytesRead = cis.read(buffer)) >= 0) { - if (isCancelled() || Thread.currentThread().isInterrupted()) - break; + try { + byte[] buffer = new byte[BUFFER_SIZE]; + + long position = 0; + int len = 0; - done += bytesRead; - - int progress = (int) ((done * 100) / length); - setProgress(progress); + while ((len = in.read(buffer)) >= 0) { + position += len; + + for (Hash hash : hashes.values()) { + hash.update(buffer, 0, len); + } + + // update progress + setProgress((int) ((position * 100) / length)); + + // check abort status + if (isCancelled() || Thread.interrupted()) { + break; + } + } + } finally { + in.close(); } } - cis.close(); - - return cis.getChecksum().getValue(); + return digest(hashes); } - @Override - public String toString() { - return String.format("%s (%s)", getClass().getSimpleName(), file.getName()); + private Map digest(Map hashes) { + Map results = new EnumMap(HashType.class); + + for (Entry entry : hashes.entrySet()) { + results.put(entry.getKey(), entry.getValue().digest()); + } + + return results; } + } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumHash.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumHash.java new file mode 100644 index 00000000..e99ae238 --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumHash.java @@ -0,0 +1,29 @@ + +package net.sourceforge.filebot.ui.panel.sfv; + + +import java.util.zip.Checksum; + + +class ChecksumHash implements Hash { + + private final Checksum checksum; + + + public ChecksumHash(Checksum checksum) { + this.checksum = checksum; + } + + + @Override + public void update(byte[] bytes, int off, int len) { + checksum.update(bytes, off, len); + } + + + @Override + public String digest() { + return String.format("%08X", checksum.getValue()); + } + +} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java index e2d88681..1004a18d 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumRow.java @@ -4,8 +4,12 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.io.File; import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Set; import net.sourceforge.filebot.FileBotUtilities; @@ -14,48 +18,26 @@ public class ChecksumRow { private String name; - private HashMap checksumMap = new HashMap(); + private Map hashes = new HashMap(4); + private State state = State.UNKNOWN; /** * Checksum that is embedded in the file name (e.g. Test[49A93C5F].txt) */ - private final Long embeddedChecksum; + private String embeddedChecksum; public static enum State { + UNKNOWN, OK, WARNING, - ERROR, - UNKNOWN; + ERROR } public ChecksumRow(String name) { this.name = name; - this.embeddedChecksum = getEmbeddedChecksum(name); - } - - - /** - * Try to parse a CRC32 checksum from the given file name. The checksum is assumed to be in - * brackets. - * - *
-	 * e.g.
-	 * Test[49A93C5F].txt
-	 * 
- * - * @param file name that contains a checksum - * @return the checksum or null, if parameter did not contain a checksum - */ - private static Long getEmbeddedChecksum(String name) { - // look for a checksum pattern like [49A93C5F] - String match = FileBotUtilities.getEmbeddedChecksum(name); - - if (match != null) - return Long.parseLong(match, 16); - - return null; + this.embeddedChecksum = FileBotUtilities.getEmbeddedChecksum(name); } @@ -65,50 +47,91 @@ public class ChecksumRow { public State getState() { - HashSet checksums = new HashSet(); - - for (Checksum checksum : getChecksums()) { - if (checksum.getState() == Checksum.State.READY) { - checksums.add(checksum.getChecksum()); - } else if (checksum.getState() == Checksum.State.ERROR) { + return state; + } + + + public ChecksumCell getChecksum(File root) { + return hashes.get(root); + } + + + public Collection values() { + return Collections.unmodifiableCollection(hashes.values()); + } + + + public void add(ChecksumCell entry) { + hashes.put(entry.getRoot(), entry); + updateState(); + } + + + public void updateState() { + // update state + state = getState(hashes.values()); + } + + + protected State getState(Collection entries) { + // check states before we bother comparing the hash values + for (ChecksumCell entry : entries) { + if (entry.getState() == ChecksumCell.State.ERROR) { + // one error cell -> error state return State.ERROR; - } else { + } else if (entry.getState() != ChecksumCell.State.READY) { + // one cell that is not ready yet -> unknown state return State.UNKNOWN; } } - if (checksums.size() > 1) { - // checksums do not match + // compare hash values + Set checksumSet = new HashSet(2); + Set verdictSet = EnumSet.noneOf(State.class); + + for (HashType type : HashType.values()) { + checksumSet.clear(); + + for (ChecksumCell entry : entries) { + String checksum = entry.getChecksum(type); + + if (checksum != null) { + checksumSet.add(checksum); + } + } + + verdictSet.add(getVerdict(checksumSet)); + } + + // ERROR > WARNING > OK > UNKOWN + return Collections.max(verdictSet); + } + + + protected State getVerdict(Set checksumSet) { + if (checksumSet.size() < 1) { + // no hash values + return State.UNKNOWN; + } else if (checksumSet.size() > 1) { + // hashes don't match, something is wrong return State.ERROR; + } else { + // all hashes match + if (embeddedChecksum != null) { + String checksum = checksumSet.iterator().next(); + + if (checksum.length() == embeddedChecksum.length() && !checksum.equalsIgnoreCase(embeddedChecksum)) { + return State.WARNING; + } + } + + return State.OK; } - - if (!checksums.isEmpty() && embeddedChecksum != null) { - // check if the embedded checksum matches - if (!checksums.contains(embeddedChecksum)) - return State.WARNING; - } - - return State.OK; } - public Checksum getChecksum(File column) { - return checksumMap.get(column); + @Override + public String toString() { + return String.format("%s %s", name, hashes); } - - - public Collection getChecksums() { - return checksumMap.values(); - } - - - public void putChecksum(File column, Checksum checksum) { - checksumMap.put(column, checksum); - } - - - public void removeChecksum(File column) { - checksumMap.remove(column); - } - } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableCellRenderer.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableCellRenderer.java index 78649694..9d1f236b 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableCellRenderer.java @@ -23,24 +23,25 @@ class ChecksumTableCellRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, null, isSelected, false, row, column); - if (value == null) - return this; - - Checksum checksum = (Checksum) value; - - switch (checksum.getState()) { - case READY: - setText(checksum.getChecksumString()); - return this; - case PENDING: - setText("Pending ..."); - return this; - case ERROR: - setText(checksum.getErrorMessage()); - return this; - default: - return progressBarRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (value instanceof ChecksumCell) { + ChecksumCell checksum = (ChecksumCell) value; + + switch (checksum.getState()) { + case READY: + setText(checksum.getChecksum(HashType.CRC32)); + break; + case PENDING: + setText("Pending ..."); + break; + case ERROR: + setText(checksum.getError().getMessage()); + break; + default: + return progressBarRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } } + + return this; } @@ -61,9 +62,11 @@ class ChecksumTableCellRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - Checksum checksum = (Checksum) value; + ChecksumComputationTask task = ((ChecksumCell) value).getTask(); - progressBar.setValue(checksum.getProgress()); + if (task != null) { + progressBar.setValue(task.getProgress()); + } if (isSelected) { this.setBackground(table.getSelectionBackground()); diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableExportHandler.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableExportHandler.java index 77cd5ad1..57159188 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableExportHandler.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableExportHandler.java @@ -5,11 +5,9 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.io.File; import java.io.IOException; import java.io.PrintWriter; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Map; -import java.util.Map.Entry; - +import java.util.Formatter; +import net.sourceforge.filebot.Settings; import net.sourceforge.filebot.ui.transfer.TextFileExportHandler; import net.sourceforge.tuned.FileUtilities; @@ -26,19 +24,19 @@ public class ChecksumTableExportHandler extends TextFileExportHandler { @Override public boolean canExport() { - return model.getRowCount() > 0 && model.getChecksumColumnCount() > 0; + return model.getRowCount() > 0 && model.getChecksumList().size() > 0; } @Override - public void export(PrintWriter out) { - export(out, model.getChecksumColumn(0)); + public void export(Formatter out) { + export(out, model.getChecksumList().get(0)); } @Override public String getDefaultFileName() { - return getDefaultFileName(model.getChecksumColumn(0)); + return getDefaultFileName(model.getChecksumList().get(0)); } @@ -46,27 +44,21 @@ public class ChecksumTableExportHandler extends TextFileExportHandler { PrintWriter out = new PrintWriter(file, "UTF-8"); try { - export(out, column); + export(new Formatter(out), column); } finally { out.close(); } } - public void export(PrintWriter out, File column) { + public void export(Formatter out, File column) { + out.format("; Generated by %s on %tF at % checksumMap = model.getChecksumColumn(column); - - for (Entry entry : checksumMap.entrySet()) { - out.println(String.format("%s %s", entry.getKey(), entry.getValue())); + for (ChecksumRow row : model) { + //TODO select hash type + out.format("%s %s%n", row.getName(), row.getChecksum(column).getChecksum(HashType.CRC32)); } } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableModel.java b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableModel.java index 52e54faf..15869f11 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableModel.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/ChecksumTableModel.java @@ -2,15 +2,20 @@ package net.sourceforge.filebot.ui.panel.sfv; +import static javax.swing.event.TableModelEvent.UPDATE; + import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; +import java.util.AbstractList; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; @@ -19,92 +24,86 @@ import javax.swing.table.TableModel; import net.sourceforge.tuned.FileUtilities; -class ChecksumTableModel extends AbstractTableModel { +class ChecksumTableModel extends AbstractTableModel implements Iterable { - private List rows = new ArrayList(50); + private final IndexedMap rows = new IndexedMap() { + + @Override + public String key(ChecksumRow value) { + return value.getName(); + } + }; - /** - * Hash map for fast access to the row of a given name - */ - private Map rowMap = new HashMap(50); - - private List columns = new ArrayList(); - - /** - * Checksum start at column 3 - */ - private static final int checksumColumnOffset = 2; + private final List columns = new ArrayList(); @Override public String getColumnName(int columnIndex) { - if (columnIndex == 0) - return "State"; - - if (columnIndex == 1) - return "Name"; - - if (columnIndex >= checksumColumnOffset) { - File column = columns.get(columnIndex - checksumColumnOffset); - - // works for files too and simply returns the name unchanged - return FileUtilities.getFolderName(column); + switch (columnIndex) { + case 0: + return "State"; + case 1: + return "Name"; + default: + // works for files too and simply returns the name unchanged + return FileUtilities.getFolderName(getColumnRoot(columnIndex)); } - - return null; } @Override public Class getColumnClass(int columnIndex) { - if (columnIndex == 0) - return ChecksumRow.State.class; - - if (columnIndex == 1) - return String.class; - - if (columnIndex >= checksumColumnOffset) - return Checksum.class; - - return null; + switch (columnIndex) { + case 0: + return ChecksumRow.State.class; + case 1: + return String.class; + default: + return ChecksumCell.class; + } } + public File getColumnRoot(int columnIndex) { + return columns.get(columnIndex - 2); + } + + + @Override public int getColumnCount() { - return checksumColumnOffset + getChecksumColumnCount(); + return columns.size() + 2; } - public int getChecksumColumnCount() { - return columns.size(); - } - - - public List getChecksumColumns() { + public List getChecksumList() { return Collections.unmodifiableList(columns); } + @Override public int getRowCount() { return rows.size(); } + @Override public Object getValueAt(int rowIndex, int columnIndex) { ChecksumRow row = rows.get(rowIndex); - if (columnIndex == 0) - return row.getState(); - - if (columnIndex == 1) - return row.getName(); - - if (columnIndex >= checksumColumnOffset) { - File column = columns.get(columnIndex - checksumColumnOffset); - return row.getChecksum(column); + switch (columnIndex) { + case 0: + return row.getState(); + case 1: + return row.getName(); + default: + return row.getChecksum(getColumnRoot(columnIndex)); } - - return null; + } + + + @Override + public Iterator iterator() { + return rows.iterator(); } @@ -112,7 +111,22 @@ class ChecksumTableModel extends AbstractTableModel { int firstRow = getRowCount(); for (ChecksumCell entry : list) { - addChecksum(entry.getName(), entry.getChecksum(), entry.getColumn()); + ChecksumRow row = rows.getByKey(entry.getName()); + + if (row == null) { + row = new ChecksumRow(entry.getName()); + rows.add(row); + } + + row.add(entry); + + // listen to changes (progress, state) + entry.addPropertyChangeListener(progressListener); + + if (!columns.contains(entry.getRoot())) { + columns.add(entry.getRoot()); + fireTableStructureChanged(); + } } int lastRow = getRowCount() - 1; @@ -123,125 +137,142 @@ class ChecksumTableModel extends AbstractTableModel { } - private void addChecksum(String name, Checksum checksum, File column) { - ChecksumRow row = rowMap.get(name); - - if (row == null) { - row = new ChecksumRow(name); - rows.add(row); - rowMap.put(name, row); - } - - row.putChecksum(column, checksum); - checksum.addPropertyChangeListener(checksumListener); - - if (!columns.contains(column)) { - columns.add(column); - fireTableStructureChanged(); - } - } - - - public void removeRows(int... rowIndices) { - ArrayList rowsToRemove = new ArrayList(rowIndices.length); - - for (int i : rowIndices) { - ChecksumRow row = rows.get(i); - rowsToRemove.add(rows.get(i)); - - for (Checksum checksum : row.getChecksums()) { - checksum.cancelComputationTask(); + public void remove(int... index) { + for (int i : index) { + for (ChecksumCell entry : rows.get(i).values()) { + entry.removePropertyChangeListener(progressListener); + entry.dispose(); } - - rowMap.remove(row.getName()); } - rows.removeAll(rowsToRemove); - fireTableRowsDeleted(rowIndices[0], rowIndices[rowIndices.length - 1]); + // remove rows + rows.removeAll(index); + + fireTableRowsDeleted(index[0], index[index.length - 1]); } public void clear() { columns.clear(); rows.clear(); - rowMap.clear(); + fireTableStructureChanged(); - - fireTableDataChanged(); } - - public File getChecksumColumn(int columnIndex) { - return columns.get(columnIndex); - } - - - public Map getChecksumColumn(File column) { - LinkedHashMap checksumMap = new LinkedHashMap(); + private final PropertyChangeListener progressListener = new PropertyChangeListener() { - for (ChecksumRow row : rows) { - Checksum checksum = row.getChecksum(column); - - if ((checksum != null) && (checksum.getState() == Checksum.State.READY)) { - checksumMap.put(row.getName(), checksum); - } - } + private final MutableTableModelEvent mutableUpdateEvent = new MutableTableModelEvent(ChecksumTableModel.this, UPDATE); - return checksumMap; - } - - private final PropertyChangeListener checksumListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { - fireTableChanged(new ChecksumTableModelEvent(ChecksumTableModel.this)); + ChecksumCell entry = (ChecksumCell) evt.getSource(); + + int index = rows.getIndexByKey(entry.getName()); + + if (index >= 0) { + rows.get(index).updateState(); + fireTableChanged(mutableUpdateEvent.setRow(index)); + } } }; - public static class ChecksumCell { + protected static class MutableTableModelEvent extends TableModelEvent { - private final String name; - private final Checksum checksum; - private final File column; - - - public ChecksumCell(String name, Checksum checksum, File column) { - this.name = name; - this.checksum = checksum; - this.column = column; + public MutableTableModelEvent(TableModel source, int type) { + super(source, 0, 0, ALL_COLUMNS, type); } - public String getName() { - return name; - } - - - public Checksum getChecksum() { - return checksum; - } - - - public File getColumn() { - return column; - } - - - @Override - public String toString() { - return getName(); + public MutableTableModelEvent setRow(int row) { + this.firstRow = row; + this.lastRow = row; + + return this; } } - public static class ChecksumTableModelEvent extends TableModelEvent { + protected static abstract class IndexedMap extends AbstractList implements Set { - public static final int CHECKSUM_PROGRESS = 10; + private final Map indexMap = new HashMap(64); + private final List list = new ArrayList(64); - public ChecksumTableModelEvent(TableModel source) { - super(source); - type = CHECKSUM_PROGRESS; + public abstract K key(V value); + + + @Override + public V get(int index) { + return list.get(index); + } + + + public V getByKey(K key) { + Integer index = indexMap.get(key); + + if (index == null) + return null; + + return get(index); + } + + + public int getIndexByKey(K key) { + Integer index = indexMap.get(key); + + if (index == null) + return -1; + + return index; + } + + + @Override + public boolean add(V value) { + K key = key(value); + Integer index = indexMap.get(key); + + if (index == null && list.add(value)) { + indexMap.put(key, lastIndexOf(value)); + return true; + } + + return false; + } + + + public void removeAll(int... index) { + // sort index array + Arrays.sort(index); + + // remove in reverse + for (int i = index.length - 1; i >= 0; i--) { + V value = list.remove(index[i]); + indexMap.remove(key(value)); + } + + updateIndexMap(); + } + + + private void updateIndexMap() { + for (int i = 0; i < list.size(); i++) { + indexMap.put(key(list.get(i)), i); + } + } + + + @Override + public int size() { + return list.size(); + } + + + @Override + public void clear() { + list.clear(); + indexMap.clear(); } } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/Hash.java b/source/net/sourceforge/filebot/ui/panel/sfv/Hash.java new file mode 100644 index 00000000..51022557 --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/sfv/Hash.java @@ -0,0 +1,12 @@ + +package net.sourceforge.filebot.ui.panel.sfv; + + +interface Hash { + + public void update(byte[] bytes, int off, int len); + + + public String digest(); + +} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/HashType.java b/source/net/sourceforge/filebot/ui/panel/sfv/HashType.java new file mode 100644 index 00000000..633dcdc9 --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/sfv/HashType.java @@ -0,0 +1,34 @@ + +package net.sourceforge.filebot.ui.panel.sfv; + + +import java.util.zip.CRC32; + + +enum HashType { + + CRC32 { + + @Override + public Hash newInstance() { + return new ChecksumHash(new CRC32()); + } + }, + MD5 { + + @Override + public Hash newInstance() { + return new MessageDigestHash("MD5"); + } + }, + SHA1 { + + @Override + public Hash newInstance() { + return new MessageDigestHash("SHA-1"); + } + }; + + public abstract Hash newInstance(); + +} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/MessageDigestHash.java b/source/net/sourceforge/filebot/ui/panel/sfv/MessageDigestHash.java new file mode 100644 index 00000000..b6b1930b --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/sfv/MessageDigestHash.java @@ -0,0 +1,41 @@ + +package net.sourceforge.filebot.ui.panel.sfv; + + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + + +class MessageDigestHash implements Hash { + + private final MessageDigest md; + + + public MessageDigestHash(String algorithm) { + try { + this.md = MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + + public MessageDigestHash(MessageDigest md) { + this.md = md; + } + + + @Override + public void update(byte[] bytes, int off, int len) { + md.update(bytes, off, len); + } + + + @Override + public String digest() { + // e.g. %032x (format for MD-5) + return String.format("%0" + (md.getDigestLength() * 2) + "x", new BigInteger(1, md.digest())); + } + +} diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/SfvPanel.java b/source/net/sourceforge/filebot/ui/panel/sfv/SfvPanel.java index 52c30cfd..717af844 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/SfvPanel.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/SfvPanel.java @@ -5,24 +5,19 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; -import java.util.List; - import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; import javax.swing.border.TitledBorder; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ui.FileBotPanel; import net.sourceforge.filebot.ui.FileTransferableMessageHandler; -import net.sourceforge.filebot.ui.SelectDialog; import net.sourceforge.filebot.ui.transfer.LoadAction; import net.sourceforge.filebot.ui.transfer.SaveAction; -import net.sourceforge.tuned.FileUtilities; import net.sourceforge.tuned.MessageHandler; import net.sourceforge.tuned.ui.TunedUtilities; @@ -82,7 +77,8 @@ public class SfvPanel extends FileBotPanel { int row = sfvTable.getSelectionModel().getMinSelectionIndex(); - sfvTable.removeRows(sfvTable.getSelectedRows()); + // remove selected rows + sfvTable.getModel().remove(sfvTable.getSelectedRows()); int maxRow = sfvTable.getRowCount() - 1; diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTable.java b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTable.java index d55cc7a8..dc1ad9c2 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTable.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTable.java @@ -14,7 +14,6 @@ import javax.swing.table.TableColumn; import javax.swing.table.TableModel; import net.sourceforge.filebot.FileBotUtilities; -import net.sourceforge.filebot.ui.panel.sfv.ChecksumTableModel.ChecksumTableModelEvent; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; @@ -27,7 +26,6 @@ class SfvTable extends JTable { public SfvTable() { - transferablePolicy = new SfvTransferablePolicy(getModel(), checksumComputationService); exportHandler = new ChecksumTableExportHandler(getModel()); @@ -48,7 +46,7 @@ class SfvTable extends JTable { // highlight CRC32 patterns in filenames in green and with smaller font-size setDefaultRenderer(String.class, new HighlightPatternCellRenderer(FileBotUtilities.EMBEDDED_CHECKSUM_PATTERN, "#009900", "smaller")); setDefaultRenderer(ChecksumRow.State.class, new StateIconTableCellRenderer()); - setDefaultRenderer(Checksum.class, new ChecksumTableCellRenderer()); + setDefaultRenderer(ChecksumCell.class, new ChecksumTableCellRenderer()); } @@ -91,6 +89,7 @@ class SfvTable extends JTable { for (int i = 0; i < getColumnCount(); i++) { TableColumn column = getColumnModel().getColumn(i); + if (i == 0) { column.setPreferredWidth(45); } else if (i == 1) { @@ -110,26 +109,15 @@ class SfvTable extends JTable { } - public void removeRows(int... rowIndices) { - getModel().removeRows(rowIndices); - } - - @Override public void tableChanged(TableModelEvent e) { - // only request repaint when progress changes. Selection will go haywire if you don't. - if (e.getType() == ChecksumTableModelEvent.CHECKSUM_PROGRESS) { - repaint(); - return; - } - + //TODO CCS in SfvPanel?? if (e.getType() == TableModelEvent.DELETE) { // remove cancelled tasks from queue checksumComputationService.purge(); } super.tableChanged(e); - } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java index 31e85d1c..84876f15 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/SfvTransferablePolicy.java @@ -5,12 +5,14 @@ package net.sourceforge.filebot.ui.panel.sfv; import static net.sourceforge.filebot.FileBotUtilities.SFV_FILES; import static net.sourceforge.tuned.FileUtilities.containsOnly; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStreamReader; +import java.util.Collections; import java.util.List; +import java.util.Scanner; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -19,14 +21,14 @@ import java.util.regex.Pattern; import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy; -class SfvTransferablePolicy extends BackgroundFileTransferablePolicy { +class SfvTransferablePolicy extends BackgroundFileTransferablePolicy { - private final ChecksumTableModel tableModel; + private final ChecksumTableModel model; private final ChecksumComputationService checksumComputationService; - public SfvTransferablePolicy(ChecksumTableModel tableModel, ChecksumComputationService checksumComputationService) { - this.tableModel = tableModel; + public SfvTransferablePolicy(ChecksumTableModel model, ChecksumComputationService checksumComputationService) { + this.model = model; this.checksumComputationService = checksumComputationService; } @@ -40,46 +42,58 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy chunks) { - tableModel.addAll(chunks); + protected void process(List chunks) { + model.addAll(chunks); } - protected void loadSfvFile(File sfvFile) { + protected void loadSfvFile(File sfvFile, Executor executor) { try { - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(sfvFile), "UTF-8")); + // don't use new Scanner(File) because of BUG 6368019 (http://bugs.sun.com/view_bug.do?bug_id=6368019) + Scanner scanner = new Scanner(new FileInputStream(sfvFile), "utf-8"); - String line = null; - Pattern pattern = Pattern.compile("(.*)\\s+(\\p{XDigit}{8})"); - - while (((line = in.readLine()) != null) && !Thread.interrupted()) { - if (line.startsWith(";")) - continue; + try { + Pattern pattern = Pattern.compile("(.+)\\s+(\\p{XDigit}{8})"); - Matcher matcher = pattern.matcher(line); - - if (!matcher.matches()) - continue; - - String filename = matcher.group(1); - String checksumString = matcher.group(2); - - publish(new ChecksumTableModel.ChecksumCell(filename, new Checksum(checksumString), sfvFile)); - - File column = sfvFile.getParentFile(); - File file = new File(column, filename); - - if (file.exists()) { - publish(new ChecksumTableModel.ChecksumCell(filename, checksumComputationService.schedule(file, column), column)); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + + if (line.startsWith(";")) + continue; + + Matcher matcher = pattern.matcher(line); + + if (!matcher.matches()) + continue; + + String filename = matcher.group(1); + String checksum = matcher.group(2); + + publish(new ChecksumCell(filename, sfvFile, Collections.singletonMap(HashType.CRC32, checksum))); + + File column = sfvFile.getParentFile(); + File file = new File(column, filename); + + if (file.exists()) { + ChecksumComputationTask task = new ChecksumComputationTask(file); + + publish(new ChecksumCell(filename, column, task)); + + executor.execute(task); + } + + if (Thread.interrupted()) { + break; + } } + } finally { + scanner.close(); } - - in.close(); } catch (IOException e) { // should not happen Logger.getLogger("global").log(Level.SEVERE, e.toString(), e); @@ -95,44 +109,52 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy files) { + ExecutorService executor = checksumComputationService.newExecutor(); + try { if (containsOnly(files, SFV_FILES)) { // one or more sfv files for (File file : files) { - loadSfvFile(file); + loadSfvFile(file, executor); } } else if ((files.size() == 1) && files.get(0).isDirectory()) { // one single folder File file = files.get(0); for (File f : file.listFiles()) { - load(f, file, ""); + load(f, file, "", executor); } } else { // bunch of files for (File f : files) { - load(f, f.getParentFile(), ""); + load(f, f.getParentFile(), "", executor); } } } catch (InterruptedException e) { // supposed to happen if background execution was aborted + } finally { + executor.shutdown(); } } - protected void load(File file, File column, String prefix) throws InterruptedException { + protected void load(File file, File root, String prefix, Executor executor) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (file.isDirectory()) { // load all files in the file tree String newPrefix = prefix + file.getName() + "/"; + for (File f : file.listFiles()) { - load(f, column, newPrefix); + load(f, root, newPrefix, executor); } } else if (file.isFile()) { - publish(new ChecksumTableModel.ChecksumCell(prefix + file.getName(), checksumComputationService.schedule(file, column), column)); + ChecksumComputationTask task = new ChecksumComputationTask(file); + + publish(new ChecksumCell(prefix + file.getName(), root, task)); + + executor.execute(task); } } - } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/StateIconTableCellRenderer.java b/source/net/sourceforge/filebot/ui/panel/sfv/StateIconTableCellRenderer.java index c5071f63..3936dbab 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/StateIconTableCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/StateIconTableCellRenderer.java @@ -3,6 +3,8 @@ package net.sourceforge.filebot.ui.panel.sfv; import java.awt.Component; +import java.util.EnumMap; +import java.util.Map; import javax.swing.Icon; import javax.swing.JTable; @@ -10,17 +12,20 @@ import javax.swing.SwingConstants; import javax.swing.table.DefaultTableCellRenderer; import net.sourceforge.filebot.ResourceManager; +import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow.State; class StateIconTableCellRenderer extends DefaultTableCellRenderer { - private Icon warning = ResourceManager.getIcon("status.warning"); - private Icon error = ResourceManager.getIcon("status.error"); - private Icon unknown = ResourceManager.getIcon("status.unknown"); - private Icon ok = ResourceManager.getIcon("status.ok"); + private final Map icons = new EnumMap(State.class); public StateIconTableCellRenderer() { + icons.put(State.UNKNOWN, ResourceManager.getIcon("status.unknown")); + icons.put(State.OK, ResourceManager.getIcon("status.ok")); + icons.put(State.WARNING, ResourceManager.getIcon("status.warning")); + icons.put(State.ERROR, ResourceManager.getIcon("status.error")); + setVerticalAlignment(SwingConstants.CENTER); setHorizontalAlignment(SwingConstants.CENTER); } @@ -30,22 +35,7 @@ class StateIconTableCellRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, null, isSelected, false, row, column); - ChecksumRow.State state = (ChecksumRow.State) value; - - switch (state) { - case OK: - setIcon(ok); - break; - case ERROR: - setIcon(error); - break; - case WARNING: - setIcon(warning); - break; - case UNKNOWN: - setIcon(unknown); - break; - } + setIcon(icons.get(value)); return this; } diff --git a/source/net/sourceforge/filebot/ui/panel/sfv/TotalProgressPanel.java b/source/net/sourceforge/filebot/ui/panel/sfv/TotalProgressPanel.java index 6eb67647..abee96d2 100644 --- a/source/net/sourceforge/filebot/ui/panel/sfv/TotalProgressPanel.java +++ b/source/net/sourceforge/filebot/ui/panel/sfv/TotalProgressPanel.java @@ -2,6 +2,8 @@ package net.sourceforge.filebot.ui.panel.sfv; +import static net.sourceforge.filebot.ui.panel.sfv.ChecksumComputationService.TASK_COUNT_PROPERTY; + import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -9,6 +11,8 @@ import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.Timer; import net.sourceforge.tuned.ui.TunedUtilities; @@ -19,13 +23,13 @@ class TotalProgressPanel extends Box { private final JProgressBar progressBar = new JProgressBar(0, 0); - private final ChecksumComputationService checksumComputationService; + private final ChecksumComputationService service; public TotalProgressPanel(ChecksumComputationService checksumComputationService) { super(BoxLayout.Y_AXIS); - this.checksumComputationService = checksumComputationService; + this.service = checksumComputationService; // invisible by default setVisible(false); @@ -38,40 +42,49 @@ class TotalProgressPanel extends Box { add(progressBar); - checksumComputationService.addPropertyChangeListener(progressListener); + checksumComputationService.addPropertyChangeListener(TASK_COUNT_PROPERTY, progressListener); } - private PropertyChangeListener progressListener = new PropertyChangeListener() { + private final PropertyChangeListener progressListener = new PropertyChangeListener() { + + private Timer setVisibleTimer; + public void propertyChange(PropertyChangeEvent evt) { + final int completedTaskCount = service.getCompletedTaskCount(); + final int totalTaskCount = service.getTotalTaskCount(); - String property = evt.getPropertyName(); - - if (property == ChecksumComputationService.ACTIVE_PROPERTY) { - Boolean active = (Boolean) evt.getNewValue(); + // invoke on EDT + SwingUtilities.invokeLater(new Runnable() { - if (active) { - TunedUtilities.invokeLater(millisToSetVisible, new Runnable() { - - @Override - public void run() { - setVisible(checksumComputationService.isActive()); + @Override + public void run() { + if (completedTaskCount < totalTaskCount) { + if (setVisibleTimer == null) { + setVisibleTimer = TunedUtilities.invokeLater(millisToSetVisible, new Runnable() { + + @Override + public void run() { + setVisible(service.getTaskCount() > service.getCompletedTaskCount()); + } + }); } - }); - } else { - // hide when not active - setVisible(false); - } - } else if (property == ChecksumComputationService.REMAINING_TASK_COUNT_PROPERTY) { - - int taskCount = checksumComputationService.getActiveSessionTaskCount(); - int progress = taskCount - checksumComputationService.getRemainingTaskCount(); - - progressBar.setValue(progress); - progressBar.setMaximum(taskCount); - - progressBar.setString(progressBar.getValue() + " / " + progressBar.getMaximum()); - } + } else { + if (setVisibleTimer != null) { + setVisibleTimer.stop(); + setVisibleTimer = null; + } + + // hide when not active + setVisible(false); + } + + progressBar.setValue(completedTaskCount); + progressBar.setMaximum(totalTaskCount); + + progressBar.setString(completedTaskCount + " / " + totalTaskCount); + }; + }); } }; diff --git a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackagePanel.java b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackagePanel.java index d0ea07c7..75b2dbae 100644 --- a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackagePanel.java +++ b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackagePanel.java @@ -9,7 +9,8 @@ import java.util.EventListener; import javax.swing.JComponent; import javax.swing.JList; -import javax.swing.JScrollPane; +import net.sourceforge.filebot.web.SubtitleDescriptor; +import net.sourceforge.tuned.DownloadTask; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; @@ -24,7 +25,33 @@ public class SubtitlePackagePanel extends JComponent { public SubtitlePackagePanel() { setLayout(new BorderLayout()); - add(new JScrollPane(createList()), BorderLayout.CENTER); + add(createList(), BorderLayout.CENTER); + model.add(new SubtitlePackage(new SubtitleDescriptor() { + + @Override + public DownloadTask createDownloadTask() { + return null; + } + + + @Override + public String getArchiveType() { + return ArchiveType.ZIP.getExtension(); + } + + + @Override + public String getLanguageName() { + return "english"; + } + + + @Override + public String getName() { + return "Firefly 1x01 The Train Job.srt"; + } + + })); } @@ -33,11 +60,15 @@ public class SubtitlePackagePanel extends JComponent { } - protected JList createList() { + protected JComponent createList() { ObservableElementList observableList = new ObservableElementList(model, new SubtitlePackageConnector()); JList list = new JList(new EventListModel(observableList)); + list.setCellRenderer(new SubtitleCellRenderer()); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + return list; } @@ -51,9 +82,14 @@ public class SubtitlePackagePanel extends JComponent { private ObservableElementList list = null; - public EventListener installListener(SubtitlePackage element) { - PropertyChangeListener listener = new SubtitlePackageListener(element); - element.getDownloadTask().addPropertyChangeListener(listener); + public EventListener installListener(final SubtitlePackage element) { + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + list.elementChanged(element); + } + }; return listener; } @@ -64,24 +100,10 @@ public class SubtitlePackagePanel extends JComponent { } - public void setObservableElementList(ObservableElementList list) { - this.list = list; - } - - - protected class SubtitlePackageListener implements PropertyChangeListener { - - private final SubtitlePackage subtitlePackage; - - - public SubtitlePackageListener(SubtitlePackage subtitlePackage) { - this.subtitlePackage = subtitlePackage; - } - - - public void propertyChange(PropertyChangeEvent evt) { - list.elementChanged(subtitlePackage); - } + @SuppressWarnings("unchecked") + @Override + public void setObservableElementList(ObservableElementList list) { + this.list = (ObservableElementList) list; } } diff --git a/source/net/sourceforge/filebot/ui/transfer/BackgroundFileTransferablePolicy.java b/source/net/sourceforge/filebot/ui/transfer/BackgroundFileTransferablePolicy.java index 33ba611a..0c5cce18 100644 --- a/source/net/sourceforge/filebot/ui/transfer/BackgroundFileTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/transfer/BackgroundFileTransferablePolicy.java @@ -8,6 +8,8 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.SwingWorker; @@ -76,7 +78,7 @@ public abstract class BackgroundFileTransferablePolicy extends FileTransferab } - private class BackgroundWorker extends SwingWorker { + private class BackgroundWorker extends SwingWorker { private final List files; @@ -87,8 +89,13 @@ public abstract class BackgroundFileTransferablePolicy extends FileTransferab @Override - protected Object doInBackground() { - load(files); + protected Void doInBackground() { + try { + load(files); + } catch (Exception e) { + Logger.getLogger("global").log(Level.WARNING, e.getMessage(), e); + } + return null; } diff --git a/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java b/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java index a7fef7c0..1020fc2b 100644 --- a/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java @@ -23,7 +23,7 @@ public abstract class FileTransferablePolicy extends TransferablePolicy { /** * Pattern that will match Windows (\r\n), Unix (\n) and Mac (\r) line separators. */ - public static final Pattern LINE_SEPARATOR = Pattern.compile("\r?\n|\r\n?"); + public static final Pattern LINE_SEPARATOR = Pattern.compile("\r\n|[\r\n]"); @Override diff --git a/source/net/sourceforge/filebot/ui/transfer/TextFileExportHandler.java b/source/net/sourceforge/filebot/ui/transfer/TextFileExportHandler.java index 7a21a2b9..b356d7de 100644 --- a/source/net/sourceforge/filebot/ui/transfer/TextFileExportHandler.java +++ b/source/net/sourceforge/filebot/ui/transfer/TextFileExportHandler.java @@ -6,7 +6,7 @@ import java.awt.datatransfer.Transferable; import java.io.File; import java.io.IOException; import java.io.PrintWriter; -import java.io.StringWriter; +import java.util.Formatter; import javax.swing.JComponent; import javax.swing.TransferHandler; @@ -17,7 +17,7 @@ public abstract class TextFileExportHandler implements TransferableExportHandler public abstract boolean canExport(); - public abstract void export(PrintWriter out); + public abstract void export(Formatter out); public abstract String getDefaultFileName(); @@ -28,7 +28,7 @@ public abstract class TextFileExportHandler implements TransferableExportHandler PrintWriter out = new PrintWriter(file, "UTF-8"); try { - export(out); + export(new Formatter(out)); } finally { out.close(); } @@ -47,8 +47,8 @@ public abstract class TextFileExportHandler implements TransferableExportHandler @Override public Transferable createTransferable(JComponent c) { // get transfer data - StringWriter buffer = new StringWriter(); - export(new PrintWriter(buffer)); + StringBuilder buffer = new StringBuilder(); + export(new Formatter(buffer)); return new LazyTextFileTransferable(buffer.toString(), getDefaultFileName()); } diff --git a/source/net/sourceforge/filebot/web/AnidbClient.java b/source/net/sourceforge/filebot/web/AnidbClient.java index 94b8091e..87b8485c 100644 --- a/source/net/sourceforge/filebot/web/AnidbClient.java +++ b/source/net/sourceforge/filebot/web/AnidbClient.java @@ -14,7 +14,6 @@ import java.net.URI; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -135,7 +134,7 @@ public class AnidbClient implements EpisodeListClient { @Override - public Collection getEpisodeList(SearchResult searchResult, int season) throws Exception { + public List getEpisodeList(SearchResult searchResult, int season) throws Exception { throw new UnsupportedOperationException(); } diff --git a/source/net/sourceforge/filebot/web/EpisodeListClient.java b/source/net/sourceforge/filebot/web/EpisodeListClient.java index a81671cd..3704d9eb 100644 --- a/source/net/sourceforge/filebot/web/EpisodeListClient.java +++ b/source/net/sourceforge/filebot/web/EpisodeListClient.java @@ -3,23 +3,23 @@ package net.sourceforge.filebot.web; import java.net.URI; -import java.util.Collection; +import java.util.List; import javax.swing.Icon; public interface EpisodeListClient { - public Collection search(String query) throws Exception; + public List search(String query) throws Exception; public boolean hasSingleSeasonSupport(); - public Collection getEpisodeList(SearchResult searchResult) throws Exception; + public List getEpisodeList(SearchResult searchResult) throws Exception; - public Collection getEpisodeList(SearchResult searchResult, int season) throws Exception; + public List getEpisodeList(SearchResult searchResult, int season) throws Exception; public URI getEpisodeListLink(SearchResult searchResult); diff --git a/source/net/sourceforge/filebot/web/SubtitleClient.java b/source/net/sourceforge/filebot/web/SubtitleClient.java index 1cba315a..52ada293 100644 --- a/source/net/sourceforge/filebot/web/SubtitleClient.java +++ b/source/net/sourceforge/filebot/web/SubtitleClient.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.web; import java.net.URI; -import java.util.Collection; +import java.util.List; import java.util.Locale; import javax.swing.Icon; @@ -11,10 +11,10 @@ import javax.swing.Icon; public interface SubtitleClient { - public Collection search(String query) throws Exception; + public List search(String query) throws Exception; - public Collection getSubtitleList(SearchResult searchResult, Locale language) throws Exception; + public List getSubtitleList(SearchResult searchResult, Locale language) throws Exception; public URI getSubtitleListLink(SearchResult searchResult, Locale language); diff --git a/source/net/sourceforge/tuned/ExceptionUtil.java b/source/net/sourceforge/tuned/ExceptionUtilities.java similarity index 86% rename from source/net/sourceforge/tuned/ExceptionUtil.java rename to source/net/sourceforge/tuned/ExceptionUtilities.java index c38d9ed8..adacef40 100644 --- a/source/net/sourceforge/tuned/ExceptionUtil.java +++ b/source/net/sourceforge/tuned/ExceptionUtilities.java @@ -2,7 +2,7 @@ package net.sourceforge.tuned; -public final class ExceptionUtil { +public final class ExceptionUtilities { public static Throwable getRootCause(Throwable t) { while (t.getCause() != null) { @@ -25,7 +25,7 @@ public final class ExceptionUtil { /** * Dummy constructor to prevent instantiation. */ - private ExceptionUtil() { + private ExceptionUtilities() { throw new UnsupportedOperationException(); } diff --git a/source/net/sourceforge/tuned/PreferencesMap.java b/source/net/sourceforge/tuned/PreferencesMap.java index 93cc22ad..3aaa5da4 100644 --- a/source/net/sourceforge/tuned/PreferencesMap.java +++ b/source/net/sourceforge/tuned/PreferencesMap.java @@ -282,7 +282,7 @@ public class PreferencesMap implements Map { return constructor.newInstance(stringValue); } catch (InvocationTargetException e) { // try to throw the cause directly, e.g. NumberFormatException - throw ExceptionUtil.asRuntimeException(e.getCause()); + throw ExceptionUtilities.asRuntimeException(e.getCause()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/source/net/sourceforge/tuned/ui/SimpleLabelProvider.java b/source/net/sourceforge/tuned/ui/SimpleLabelProvider.java index a1a3b661..ceb19cec 100644 --- a/source/net/sourceforge/tuned/ui/SimpleLabelProvider.java +++ b/source/net/sourceforge/tuned/ui/SimpleLabelProvider.java @@ -7,7 +7,7 @@ import java.util.Arrays; import javax.swing.Icon; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; /** @@ -73,7 +73,7 @@ public class SimpleLabelProvider implements LabelProvider { try { return (String) getTextMethod.invoke(value); } catch (Exception e) { - throw ExceptionUtil.asRuntimeException(e); + throw ExceptionUtilities.asRuntimeException(e); } } @@ -83,7 +83,7 @@ public class SimpleLabelProvider implements LabelProvider { try { return (Icon) getIconMethod.invoke(value); } catch (Exception e) { - throw ExceptionUtil.asRuntimeException(e); + throw ExceptionUtilities.asRuntimeException(e); } } diff --git a/source/net/sourceforge/tuned/ui/TunedUtilities.java b/source/net/sourceforge/tuned/ui/TunedUtilities.java index 1b7ae859..284d258f 100644 --- a/source/net/sourceforge/tuned/ui/TunedUtilities.java +++ b/source/net/sourceforge/tuned/ui/TunedUtilities.java @@ -24,7 +24,7 @@ import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.Timer; -import net.sourceforge.tuned.ExceptionUtil; +import net.sourceforge.tuned.ExceptionUtilities; public final class TunedUtilities { @@ -120,7 +120,7 @@ public final class TunedUtilities { return listener; } catch (Exception e) { - throw ExceptionUtil.asRuntimeException(e); + throw ExceptionUtilities.asRuntimeException(e); } } @@ -139,7 +139,7 @@ public final class TunedUtilities { try { firePropertyChange.invoke(target, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } catch (Exception e) { - throw ExceptionUtil.asRuntimeException(e); + throw ExceptionUtilities.asRuntimeException(e); } } }