--- /dev/null
+/* \r
+@ITMillApache2LicenseForJavaFiles@\r
+ */\r
+\r
+package com.vaadin.data.util;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.BufferedWriter;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.io.OutputStreamWriter;\r
+import java.nio.charset.Charset;\r
+import java.util.LinkedList;\r
+\r
+import com.vaadin.data.Property;\r
+\r
+/**\r
+ * Property implementation for wrapping a text file.\r
+ * \r
+ * Supports reading and writing of a File from/to String. ValueChangeNotifiers\r
+ * are supported, but only fire when setValue(Object) is explicitly called.\r
+ */\r
+@SuppressWarnings("serial")\r
+public class TextFileProperty implements Property, Property.ValueChangeNotifier {\r
+\r
+ private File file;\r
+ private boolean readonly;\r
+ private Charset charset = null;\r
+ private LinkedList<Property.ValueChangeListener> valueChangeListeners = null;\r
+\r
+ /**\r
+ * Wrap given file with property interface.\r
+ * \r
+ * Setting the file to null works, but getValue() will return null.\r
+ * \r
+ * @param file\r
+ * File to be wrapped.\r
+ */\r
+ public TextFileProperty(File file) {\r
+ this.file = file;\r
+ }\r
+\r
+ /**\r
+ * Wrap the given file with the property interface and specify character\r
+ * set.\r
+ * \r
+ * Setting the file to null works, but getValue() will return null.\r
+ * \r
+ * @param file\r
+ * File to be wrapped.\r
+ * @param charset\r
+ * Charset to be used for reading and writing the file.\r
+ */\r
+ public TextFileProperty(File file, Charset charset) {\r
+ this.file = file;\r
+ this.charset = charset;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.vaadin.data.Property#getType()\r
+ */\r
+ public Class<?> getType() {\r
+ return String.class;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.vaadin.data.Property#getValue()\r
+ */\r
+ public Object getValue() {\r
+ if (file == null) {\r
+ return null;\r
+ }\r
+ try {\r
+ FileInputStream fis = new FileInputStream(file);\r
+ InputStreamReader isr = charset == null ? new InputStreamReader(fis)\r
+ : new InputStreamReader(fis, charset);\r
+ BufferedReader r = new BufferedReader(isr);\r
+ StringBuilder b = new StringBuilder();\r
+ char buf[] = new char[8 * 1024];\r
+ int len;\r
+ while ((len = r.read(buf)) != -1) {\r
+ b.append(buf, 0, len);\r
+ }\r
+ r.close();\r
+ isr.close();\r
+ fis.close();\r
+ return b.toString();\r
+ } catch (FileNotFoundException e) {\r
+ return null;\r
+ } catch (IOException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.vaadin.data.Property#isReadOnly()\r
+ */\r
+ public boolean isReadOnly() {\r
+ return file == null || readonly || !file.canWrite();\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.vaadin.data.Property#setReadOnly(boolean)\r
+ */\r
+ public void setReadOnly(boolean newStatus) {\r
+ readonly = newStatus;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.vaadin.data.Property#setValue(java.lang.Object)\r
+ */\r
+ public void setValue(Object newValue) throws ReadOnlyException {\r
+ if (isReadOnly()) {\r
+ throw new ReadOnlyException();\r
+ }\r
+ if (file == null) {\r
+ return;\r
+ }\r
+\r
+ try {\r
+ FileOutputStream fos = new FileOutputStream(file);\r
+ OutputStreamWriter osw = charset == null ? new OutputStreamWriter(\r
+ fos) : new OutputStreamWriter(fos, charset);\r
+ BufferedWriter w = new BufferedWriter(osw);\r
+ w.append(newValue.toString());\r
+ w.flush();\r
+ w.close();\r
+ osw.close();\r
+ fos.close();\r
+ fireValueChange();\r
+ } catch (IOException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see java.lang.Object#toString()\r
+ */\r
+ @Override\r
+ public String toString() {\r
+ return (String) getValue();\r
+ }\r
+\r
+ /* Events */\r
+\r
+ /**\r
+ * An <code>Event</code> object specifying the TextFileProperty whose value\r
+ * has changed.\r
+ */\r
+ private class ValueChangeEvent extends java.util.EventObject implements\r
+ Property.ValueChangeEvent {\r
+\r
+ /**\r
+ * Constructs a new value change event for this object.\r
+ * \r
+ * @param source\r
+ * the source object of the event.\r
+ */\r
+ protected ValueChangeEvent(TextFileProperty source) {\r
+ super(source);\r
+ }\r
+\r
+ /**\r
+ * Gets the Property whose read-only state has changed.\r
+ * \r
+ * @return source the Property of the event.\r
+ */\r
+ public Property getProperty() {\r
+ return (Property) getSource();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes a previously registered value change listener.\r
+ * \r
+ * @param listener\r
+ * the listener to be removed.\r
+ */\r
+ public void removeListener(Property.ValueChangeListener listener) {\r
+ if (valueChangeListeners != null) {\r
+ valueChangeListeners.remove(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Registers a new value change listener for this TextFileProperty.\r
+ * \r
+ * @param listener\r
+ * the new Listener to be registered\r
+ */\r
+ public void addListener(Property.ValueChangeListener listener) {\r
+ if (valueChangeListeners == null) {\r
+ valueChangeListeners = new LinkedList();\r
+ }\r
+ valueChangeListeners.add(listener);\r
+ }\r
+\r
+ /**\r
+ * Sends a value change event to all registered listeners.\r
+ */\r
+ private void fireValueChange() {\r
+ if (valueChangeListeners != null) {\r
+ final Object[] l = valueChangeListeners.toArray();\r
+ final ValueChangeEvent event = new ValueChangeEvent(this);\r
+ for (int i = 0; i < l.length; i++) {\r
+ ((ValueChangeListener) l[i]).valueChange(event);\r
+ }\r
+ }\r
+ }\r
+\r
+}\r