-/*******************************************************************************\r
- * Copyright (c) 2010- Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- * \r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.databoard.accessor.file;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.lang.ref.ReferenceQueue;\r
-import java.lang.ref.WeakReference;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.accessor.binary.BinaryObject;\r
-import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
-import org.simantics.databoard.accessor.error.AccessorException;\r
-import org.simantics.databoard.accessor.impl.AccessorParams;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.util.binary.BinaryFile;\r
-\r
-/**\r
- * File library handles sharing of file accessors and automatic closing of files.\r
- * <p>\r
- * On call of getFile or createFile the file library opens a file and returns a \r
- * file accessor. In concecutive runs the same accessor instance is returned, \r
- * unless the file was garbage collected.\r
- *\r
- * The shared accessor instances are not concurrent-use-safe.\r
- * \r
- * <p>\r
- * The file handles are actually closed by two ways:\r
- * a) File accessor are garbage collected and the the user calls {@link FileLibrary#expunge()}\r
- * b) The user invokes {@link FileLibrary#close()} in the FileLibrary.\r
- * \r
- * Files are flushed before closed.\r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class FileLibrary {\r
-\r
- /** Files */\r
- Map<File, Entry> files = new HashMap<File, Entry>(); \r
- \r
- /** Queue */ \r
- ReferenceQueue<FileVariantAccessor> queue = new ReferenceQueue<FileVariantAccessor>();\r
- \r
- /** Acessor params */\r
- AccessorParams params;\r
- \r
- /**\r
- * Create new file library\r
- */\r
- public FileLibrary() {\r
- params = AccessorParams.DEFAULT;\r
- }\r
-\r
- /**\r
- * Create new file library\r
- */\r
- public FileLibrary(AccessorParams params) {\r
- this.params = params;\r
- }\r
-\r
- /**\r
- * Get existing open file accessor.\r
- * \r
- * @param file\r
- * @return file or null\r
- * @throws IOException \r
- * @throws AccessorConstructionException \r
- */\r
- public FileVariantAccessor getExistingFile(File file) throws AccessorConstructionException {\r
- file = file.getAbsoluteFile();\r
- Entry ref = files.get(file);\r
- FileVariantAccessor accessor = ref==null ? null : ref.get();\r
- if (ref!=null && !ref.file.isOpen()) {\r
- files.remove(file);\r
- return null;\r
- }\r
- expunge();\r
- return accessor;\r
- }\r
- \r
- /**\r
- * Open file or get an existing file accessor.\r
- * The caller must not close the file, it is closed upon garbage collection\r
- * or when FileLibrary is closed. \r
- * \r
- * @param file\r
- * @return an accessor to the contents of a file\r
- * @throws IOException \r
- * @throws AccessorConstructionException \r
- */\r
- public FileVariantAccessor getFile(File file) throws AccessorConstructionException {\r
- file = file.getAbsoluteFile();\r
- Entry ref = files.get(file);\r
- FileVariantAccessor accessor = ref==null ? null : ref.get();\r
- expunge();\r
- if (ref!=null && !ref.file.isOpen()) {\r
- files.remove(file);\r
- ref = null;\r
- }\r
- \r
- \r
- // Open file\r
- if (accessor == null) {\r
- BinaryFile bf = ref!=null ? ref.file : null;\r
- if (bf==null) {\r
- try {\r
- bf = new BinaryFile(file);\r
- } catch (IOException e1) {\r
- throw new AccessorConstructionException(e1);\r
- }\r
- }\r
- accessor = (FileVariantAccessor) BinaryObject.createAccessor(bf, Datatypes.VARIANT, params);\r
- Entry e = new Entry(bf, accessor); \r
- files.put(file, e);\r
- }\r
- return accessor;\r
- }\r
- \r
- /**\r
- * Create a new file and put it in the library.\r
- * If the file exists it is overwritten. \r
- *\r
- * @param file\r
- * @return accessor to contents of a file\r
- * @throws AccessorConstructionException \r
- */\r
- public FileVariantAccessor createFile(File file) throws AccessorConstructionException {\r
- file = file.getAbsoluteFile();\r
- Entry ref = files.get(file);\r
- FileVariantAccessor accessor = ref==null ? null : ref.get();\r
- expunge();\r
- if (ref!=null && !ref.file.isOpen()) {\r
- files.remove(file);\r
- ref = null;\r
- }\r
- \r
- // Create a new file\r
- if (accessor == null) {\r
- BinaryFile bf = ref!=null ? ref.file : null;\r
- if (bf==null) {\r
- try {\r
- file.createNewFile();\r
- bf = new BinaryFile(file);\r
- } catch (IOException e1) {\r
- throw new AccessorConstructionException(e1);\r
- }\r
- }\r
- accessor = (FileVariantAccessor) BinaryObject.createAccessor(bf, Datatypes.VARIANT, params);\r
- Binding vb;\r
- try {\r
- vb = Bindings.getBinding(void.class);\r
- Object vv = vb.createDefault();\r
- accessor.setContentValue(vb, vv);\r
- } catch (BindingConstructionException e1) {\r
- throw new AccessorConstructionException(e1);\r
- } catch (AccessorException e) {\r
- throw new AccessorConstructionException(e);\r
- } catch (BindingException e) {\r
- throw new AccessorConstructionException(e);\r
- }\r
- \r
- Entry e = new Entry(bf, accessor); \r
- files.put(file, e); \r
- }\r
-\r
- return accessor;\r
- }\r
- \r
- public boolean deleteFile(File file) throws AccessorException { \r
- file = file.getAbsoluteFile();\r
- expunge();\r
- Entry ref = files.remove(file);\r
- if (ref!=null) {\r
- FileVariantAccessor accessor = ref.get();\r
- if (accessor!=null) {\r
- accessor.close();\r
- accessor = null;\r
- } else {\r
- try {\r
- ref.file.close();\r
- } catch (IOException e) {\r
- throw new AccessorException(e);\r
- }\r
- }\r
- }\r
- expunge();\r
- \r
- if (!file.exists()) {\r
- return true;\r
- }\r
- boolean ok = file.delete();\r
- return ok;\r
- }\r
- \r
-\r
- /**\r
- * Close unused file accessors. \r
- */\r
- public void expunge() {\r
- Entry e;\r
- while ( (e = (Entry) queue.poll()) != null) {\r
-// System.out.println("expunging "+e.file.file());\r
- files.remove(e.file.file());\r
- try {\r
- e.file.close();\r
- } catch (IOException e1) {\r
- e1.printStackTrace();\r
- }\r
- } \r
- }\r
- \r
- /**\r
- * Close and free all files, this invalidates all existing FileAccessors.\r
- * close() doesn't invalidate FileLibrary.\r
- * \r
- */\r
- public void close() {\r
- for (Entry e : files.values()) {\r
- try {\r
-// System.out.println("closing "+e.file.file());\r
- e.file.flush();\r
- e.file.close();\r
- } catch (IOException e1) {\r
- e1.printStackTrace();\r
- }\r
- }\r
- files.clear();\r
- }\r
-\r
- class Entry extends WeakReference<FileVariantAccessor> {\r
- BinaryFile file; \r
- public Entry(BinaryFile file, FileVariantAccessor accessor) {\r
- super(accessor, FileLibrary.this.queue);\r
- this.file = file;\r
- }\r
- }\r
- \r
-}\r
-\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2010- Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.databoard.accessor.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.accessor.binary.BinaryObject;
+import org.simantics.databoard.accessor.error.AccessorConstructionException;
+import org.simantics.databoard.accessor.error.AccessorException;
+import org.simantics.databoard.accessor.impl.AccessorParams;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.util.binary.BinaryFile;
+
+/**
+ * File library handles sharing of file accessors and automatic closing of files.
+ * <p>
+ * On call of getFile or createFile the file library opens a file and returns a
+ * file accessor. In concecutive runs the same accessor instance is returned,
+ * unless the file was garbage collected.
+ *
+ * The shared accessor instances are not concurrent-use-safe.
+ *
+ * <p>
+ * The file handles are actually closed by two ways:
+ * a) File accessor are garbage collected and the the user calls {@link FileLibrary#expunge()}
+ * b) The user invokes {@link FileLibrary#close()} in the FileLibrary.
+ *
+ * Files are flushed before closed.
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class FileLibrary {
+
+ /** Files */
+ Map<File, Entry> files = new HashMap<File, Entry>();
+
+ /** Queue */
+ ReferenceQueue<FileVariantAccessor> queue = new ReferenceQueue<FileVariantAccessor>();
+
+ /** Acessor params */
+ AccessorParams params;
+
+ /**
+ * Create new file library
+ */
+ public FileLibrary() {
+ params = AccessorParams.DEFAULT;
+ }
+
+ /**
+ * Create new file library
+ */
+ public FileLibrary(AccessorParams params) {
+ this.params = params;
+ }
+
+ /**
+ * Get existing open file accessor.
+ *
+ * @param file
+ * @return file or null
+ * @throws IOException
+ * @throws AccessorConstructionException
+ */
+ public FileVariantAccessor getExistingFile(File file) throws AccessorConstructionException {
+ file = file.getAbsoluteFile();
+ Entry ref = files.get(file);
+ FileVariantAccessor accessor = ref==null ? null : ref.get();
+ if (ref!=null && !ref.file.isOpen()) {
+ files.remove(file);
+ return null;
+ }
+ expunge();
+ return accessor;
+ }
+
+ /**
+ * Open file or get an existing file accessor.
+ * The caller must not close the file, it is closed upon garbage collection
+ * or when FileLibrary is closed.
+ *
+ * @param file
+ * @return an accessor to the contents of a file
+ * @throws IOException
+ * @throws AccessorConstructionException
+ */
+ public FileVariantAccessor getFile(File file) throws AccessorConstructionException {
+ file = file.getAbsoluteFile();
+ Entry ref = files.get(file);
+ FileVariantAccessor accessor = ref==null ? null : ref.get();
+ expunge();
+ if (ref!=null && !ref.file.isOpen()) {
+ files.remove(file);
+ ref = null;
+ }
+
+
+ // Open file
+ if (accessor == null) {
+ BinaryFile bf = ref!=null ? ref.file : null;
+ if (bf==null) {
+ try {
+ bf = new BinaryFile(file);
+ } catch (IOException e1) {
+ throw new AccessorConstructionException(e1);
+ }
+ }
+ accessor = (FileVariantAccessor) BinaryObject.createAccessor(bf, Datatypes.VARIANT, params);
+ Entry e = new Entry(bf, accessor);
+ files.put(file, e);
+ }
+ return accessor;
+ }
+
+ /**
+ * Create a new file and put it in the library.
+ * If the file exists it is overwritten.
+ *
+ * @param file
+ * @return accessor to contents of a file
+ * @throws AccessorConstructionException
+ */
+ public FileVariantAccessor createFile(File file) throws AccessorConstructionException {
+ file = file.getAbsoluteFile();
+ Entry ref = files.get(file);
+ FileVariantAccessor accessor = ref==null ? null : ref.get();
+ expunge();
+ if (ref!=null && !ref.file.isOpen()) {
+ files.remove(file);
+ ref = null;
+ }
+
+ // Create a new file
+ if (accessor == null) {
+ BinaryFile bf = ref!=null ? ref.file : null;
+ if (bf==null) {
+ try {
+ file.createNewFile();
+ bf = new BinaryFile(file);
+ } catch (IOException e1) {
+ throw new AccessorConstructionException(e1);
+ }
+ }
+ accessor = (FileVariantAccessor) BinaryObject.createAccessor(bf, Datatypes.VARIANT, params);
+ Binding vb;
+ try {
+ vb = Bindings.getBinding(void.class);
+ Object vv = vb.createDefault();
+ accessor.setContentValue(vb, vv);
+ } catch (BindingConstructionException e1) {
+ throw new AccessorConstructionException(e1);
+ } catch (AccessorException e) {
+ throw new AccessorConstructionException(e);
+ } catch (BindingException e) {
+ throw new AccessorConstructionException(e);
+ }
+
+ Entry e = new Entry(bf, accessor);
+ files.put(file, e);
+ }
+
+ return accessor;
+ }
+
+ public boolean deleteFile(File file) throws AccessorException {
+ file = file.getAbsoluteFile();
+ expunge();
+ Entry ref = files.remove(file);
+ if (ref!=null) {
+ FileVariantAccessor accessor = ref.get();
+ if (accessor!=null) {
+ accessor.close();
+ accessor = null;
+ } else {
+ try {
+ ref.file.close();
+ } catch (IOException e) {
+ throw new AccessorException(e);
+ }
+ }
+ }
+ expunge();
+
+ if (!file.exists()) {
+ return true;
+ }
+ boolean ok = file.delete();
+ return ok;
+ }
+
+
+ /**
+ * Close unused file accessors.
+ */
+ public void expunge() {
+ Entry e;
+ while ( (e = (Entry) queue.poll()) != null) {
+// System.out.println("expunging "+e.file.file());
+ files.remove(e.file.file());
+ try {
+ e.file.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Close and free all files, this invalidates all existing FileAccessors.
+ * close() doesn't invalidate FileLibrary.
+ *
+ */
+ public void close() {
+ for (Entry e : files.values()) {
+ try {
+// System.out.println("closing "+e.file.file());
+ e.file.flush();
+ e.file.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ files.clear();
+ }
+
+ class Entry extends WeakReference<FileVariantAccessor> {
+ BinaryFile file;
+ public Entry(BinaryFile file, FileVariantAccessor accessor) {
+ super(accessor, FileLibrary.this.queue);
+ this.file = file;
+ }
+ }
+
+}
+
+