-package org.simantics.internal;\r
-\r
-import java.io.File;\r
-import java.io.FileFilter;\r
-import java.io.IOException;\r
-import java.util.ArrayDeque;\r
-import java.util.Collection;\r
-\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.jobs.Job;\r
-import org.simantics.utils.FileService;\r
-import org.simantics.utils.IOperation;\r
-import org.simantics.utils.IOperationListener;\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class FileServiceImpl implements FileService {\r
-\r
- private static final long DELETION_DELAY_MS = 10000;\r
- private static final long DELETION_ATTEMPT_INTERVAL_MS = 10000;\r
-\r
- private static abstract class Op<R, E extends Exception> implements IOperation<R, E> {\r
- protected boolean done;\r
- protected R result;\r
- @SuppressWarnings("unused")\r
- protected E lastException;\r
-\r
- @Override\r
- public R waitFor() throws E {\r
- synchronized(this) {\r
- while (!isDone()) {\r
- try {\r
- wait();\r
- } catch (InterruptedException e) {\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- @Override\r
- public boolean isDone() {\r
- return done;\r
- }\r
-\r
- @Override\r
- public void addListener(IOperationListener<R, E> listener) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- public abstract boolean tryExecute();\r
-\r
- }\r
-\r
- private static class Deletion extends Op<Boolean, IOException> {\r
-\r
- File f;\r
-\r
- EffortOption effort;\r
- int tries;\r
-\r
- public Deletion(File f, DeleteOption... options) {\r
- this.f = f;\r
- parseOptions(options);\r
- }\r
-\r
- private void parseOptions(DeleteOption[] options) {\r
- for (DeleteOption opt : options) {\r
- if (opt instanceof EffortOption) {\r
- effort = (EffortOption) opt;\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public boolean tryExecute() {\r
- if (effort != null) {\r
- if (tries > effort.maxTries) {\r
- // Give up.\r
- return true;\r
- }\r
- }\r
- try {\r
- deleteAll(f);\r
- lastException = null;\r
- result = true;\r
- return true;\r
- } catch (IOException e) {\r
- ++tries;\r
- lastException = e;\r
- return false;\r
- }\r
- }\r
-\r
- public void deleteAll(File dir) throws IOException {\r
- if (dir.isFile()) {\r
- if (!dir.delete())\r
- throw new IOException("Could not delete file: " + dir.getAbsolutePath());\r
- return;\r
- }\r
- if (dir.isDirectory()) {\r
- File[] fs = dir.listFiles((FileFilter) null);\r
- if (fs == null)\r
- return;\r
-\r
- for (File f : fs) {\r
- if (f.isDirectory()) {\r
- deleteAll(f);\r
- } else {\r
- if (!f.delete()) {\r
- throw new IOException("Could not delete file: " + f.getAbsolutePath());\r
- }\r
- }\r
- }\r
-\r
- if (!dir.delete()) {\r
- throw new IOException("Could not delete directory: " + dir.getAbsolutePath());\r
- }\r
- } else if (dir.exists()) {\r
- if (!dir.delete()) {\r
- throw new IOException("Could not delete file: " + dir.getAbsolutePath());\r
- }\r
- }\r
- }\r
-\r
- }\r
-\r
- private ArrayDeque<Deletion> deletionQueue = new ArrayDeque<Deletion>();\r
- private DeletionJob deletionJob = new DeletionJob();\r
-\r
- @Override\r
- public IOperation<Boolean, IOException> scheduleDeleteIfExists(File file, DeleteOption... options) {\r
- if (!file.exists())\r
- return null;\r
- synchronized (deletionQueue) {\r
- Deletion d = new Deletion(file, options);\r
- if (deletionQueue.contains(d))\r
- return null;\r
- deletionQueue.addLast(d);\r
- deletionJob.schedule(DELETION_DELAY_MS);\r
- return d;\r
- }\r
- }\r
-\r
- class DeletionJob extends Job {\r
-\r
- public DeletionJob() {\r
- super("File background deletion");\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- private <O extends Op<?,?>> void process(Collection<O> ops) {\r
- Object[] opa = ops.toArray();\r
- for (int i = 0; i < opa.length; ++i) {\r
- O op = (O) opa[i];\r
- if (op.tryExecute()) {\r
- // Success. Will be removed from queue.\r
- } else {\r
- opa[i] = null;\r
- }\r
- }\r
- synchronized (ops) {\r
- for (int i = 0; i < opa.length; ++i) {\r
- if (opa[i] != null)\r
- ops.remove(opa[i]);\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- protected IStatus run(IProgressMonitor monitor) {\r
- process(deletionQueue);\r
- if (!deletionQueue.isEmpty())\r
- schedule(DELETION_ATTEMPT_INTERVAL_MS);\r
- return Status.OK_STATUS;\r
- }\r
-\r
- }\r
-\r
-}\r
+package org.simantics.internal;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.simantics.utils.FileService;
+import org.simantics.utils.IOperation;
+import org.simantics.utils.IOperationListener;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class FileServiceImpl implements FileService {
+
+ private static final long DELETION_DELAY_MS = 10000;
+ private static final long DELETION_ATTEMPT_INTERVAL_MS = 10000;
+
+ private static abstract class Op<R, E extends Exception> implements IOperation<R, E> {
+ protected boolean done;
+ protected R result;
+ @SuppressWarnings("unused")
+ protected E lastException;
+
+ @Override
+ public R waitFor() throws E {
+ synchronized(this) {
+ while (!isDone()) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isDone() {
+ return done;
+ }
+
+ @Override
+ public void addListener(IOperationListener<R, E> listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ public abstract boolean tryExecute();
+
+ }
+
+ private static class Deletion extends Op<Boolean, IOException> {
+
+ File f;
+
+ EffortOption effort;
+ int tries;
+
+ public Deletion(File f, DeleteOption... options) {
+ this.f = f;
+ parseOptions(options);
+ }
+
+ private void parseOptions(DeleteOption[] options) {
+ for (DeleteOption opt : options) {
+ if (opt instanceof EffortOption) {
+ effort = (EffortOption) opt;
+ }
+ }
+ }
+
+ @Override
+ public boolean tryExecute() {
+ if (effort != null) {
+ if (tries > effort.maxTries) {
+ // Give up.
+ return true;
+ }
+ }
+ try {
+ deleteAll(f);
+ lastException = null;
+ result = true;
+ return true;
+ } catch (IOException e) {
+ ++tries;
+ lastException = e;
+ return false;
+ }
+ }
+
+ public void deleteAll(File dir) throws IOException {
+ if (dir.isFile()) {
+ if (!dir.delete())
+ throw new IOException("Could not delete file: " + dir.getAbsolutePath());
+ return;
+ }
+ if (dir.isDirectory()) {
+ File[] fs = dir.listFiles((FileFilter) null);
+ if (fs == null)
+ return;
+
+ for (File f : fs) {
+ if (f.isDirectory()) {
+ deleteAll(f);
+ } else {
+ if (!f.delete()) {
+ throw new IOException("Could not delete file: " + f.getAbsolutePath());
+ }
+ }
+ }
+
+ if (!dir.delete()) {
+ throw new IOException("Could not delete directory: " + dir.getAbsolutePath());
+ }
+ } else if (dir.exists()) {
+ if (!dir.delete()) {
+ throw new IOException("Could not delete file: " + dir.getAbsolutePath());
+ }
+ }
+ }
+
+ }
+
+ private ArrayDeque<Deletion> deletionQueue = new ArrayDeque<Deletion>();
+ private DeletionJob deletionJob = new DeletionJob();
+
+ @Override
+ public IOperation<Boolean, IOException> scheduleDeleteIfExists(File file, DeleteOption... options) {
+ if (!file.exists())
+ return null;
+ synchronized (deletionQueue) {
+ Deletion d = new Deletion(file, options);
+ if (deletionQueue.contains(d))
+ return null;
+ deletionQueue.addLast(d);
+ deletionJob.schedule(DELETION_DELAY_MS);
+ return d;
+ }
+ }
+
+ class DeletionJob extends Job {
+
+ public DeletionJob() {
+ super("File background deletion");
+ }
+
+ @SuppressWarnings("unchecked")
+ private <O extends Op<?,?>> void process(Collection<O> ops) {
+ Object[] opa = ops.toArray();
+ for (int i = 0; i < opa.length; ++i) {
+ O op = (O) opa[i];
+ if (op.tryExecute()) {
+ // Success. Will be removed from queue.
+ } else {
+ opa[i] = null;
+ }
+ }
+ synchronized (ops) {
+ for (int i = 0; i < opa.length; ++i) {
+ if (opa[i] != null)
+ ops.remove(opa[i]);
+ }
+ }
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ process(deletionQueue);
+ if (!deletionQueue.isEmpty())
+ schedule(DELETION_ATTEMPT_INTERVAL_MS);
+ return Status.OK_STATUS;
+ }
+
+ }
+
+}