1 package org.simantics.internal;
\r
4 import java.io.FileFilter;
\r
5 import java.io.IOException;
\r
6 import java.util.ArrayDeque;
\r
7 import java.util.Collection;
\r
9 import org.eclipse.core.runtime.IProgressMonitor;
\r
10 import org.eclipse.core.runtime.IStatus;
\r
11 import org.eclipse.core.runtime.Status;
\r
12 import org.eclipse.core.runtime.jobs.Job;
\r
13 import org.simantics.utils.FileService;
\r
14 import org.simantics.utils.IOperation;
\r
15 import org.simantics.utils.IOperationListener;
\r
18 * @author Tuukka Lehtonen
\r
20 public class FileServiceImpl implements FileService {
\r
22 private static final long DELETION_DELAY_MS = 10000;
\r
23 private static final long DELETION_ATTEMPT_INTERVAL_MS = 10000;
\r
25 private static abstract class Op<R, E extends Exception> implements IOperation<R, E> {
\r
26 protected boolean done;
\r
28 @SuppressWarnings("unused")
\r
29 protected E lastException;
\r
32 public R waitFor() throws E {
\r
33 synchronized(this) {
\r
37 } catch (InterruptedException e) {
\r
45 public boolean isDone() {
\r
50 public void addListener(IOperationListener<R, E> listener) {
\r
51 throw new UnsupportedOperationException();
\r
54 public abstract boolean tryExecute();
\r
58 private static class Deletion extends Op<Boolean, IOException> {
\r
62 EffortOption effort;
\r
65 public Deletion(File f, DeleteOption... options) {
\r
67 parseOptions(options);
\r
70 private void parseOptions(DeleteOption[] options) {
\r
71 for (DeleteOption opt : options) {
\r
72 if (opt instanceof EffortOption) {
\r
73 effort = (EffortOption) opt;
\r
79 public boolean tryExecute() {
\r
80 if (effort != null) {
\r
81 if (tries > effort.maxTries) {
\r
88 lastException = null;
\r
91 } catch (IOException e) {
\r
98 public void deleteAll(File dir) throws IOException {
\r
101 throw new IOException("Could not delete file: " + dir.getAbsolutePath());
\r
104 if (dir.isDirectory()) {
\r
105 File[] fs = dir.listFiles((FileFilter) null);
\r
109 for (File f : fs) {
\r
110 if (f.isDirectory()) {
\r
114 throw new IOException("Could not delete file: " + f.getAbsolutePath());
\r
119 if (!dir.delete()) {
\r
120 throw new IOException("Could not delete directory: " + dir.getAbsolutePath());
\r
122 } else if (dir.exists()) {
\r
123 if (!dir.delete()) {
\r
124 throw new IOException("Could not delete file: " + dir.getAbsolutePath());
\r
131 private ArrayDeque<Deletion> deletionQueue = new ArrayDeque<Deletion>();
\r
132 private DeletionJob deletionJob = new DeletionJob();
\r
135 public IOperation<Boolean, IOException> scheduleDeleteIfExists(File file, DeleteOption... options) {
\r
136 if (!file.exists())
\r
138 synchronized (deletionQueue) {
\r
139 Deletion d = new Deletion(file, options);
\r
140 if (deletionQueue.contains(d))
\r
142 deletionQueue.addLast(d);
\r
143 deletionJob.schedule(DELETION_DELAY_MS);
\r
148 class DeletionJob extends Job {
\r
150 public DeletionJob() {
\r
151 super("File background deletion");
\r
154 @SuppressWarnings("unchecked")
\r
155 private <O extends Op<?,?>> void process(Collection<O> ops) {
\r
156 Object[] opa = ops.toArray();
\r
157 for (int i = 0; i < opa.length; ++i) {
\r
159 if (op.tryExecute()) {
\r
160 // Success. Will be removed from queue.
\r
165 synchronized (ops) {
\r
166 for (int i = 0; i < opa.length; ++i) {
\r
167 if (opa[i] != null)
\r
168 ops.remove(opa[i]);
\r
174 protected IStatus run(IProgressMonitor monitor) {
\r
175 process(deletionQueue);
\r
176 if (!deletionQueue.isEmpty())
\r
177 schedule(DELETION_ATTEMPT_INTERVAL_MS);
\r
178 return Status.OK_STATUS;
\r