diff -r bd8aef593115 openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml Thu Jan 29 17:56:55 2009 +0100 +++ b/openide.filesystems/apichanges.xml Mon Feb 02 10:22:22 2009 +0100 @@ -46,6 +46,27 @@ Filesystems API + + + Read files with asText(), asBytes() and asLines() + + + + + +

+ Added + asBytes(), + + asText(encoding), + and + asLines(encoding) methods into + FileObject + to simplify reading of its content. +

+
+ +
Possibility to add FileChangeListeners on File (even not existing) diff -r bd8aef593115 openide.filesystems/nbproject/project.properties --- a/openide.filesystems/nbproject/project.properties Thu Jan 29 17:56:55 2009 +0100 +++ b/openide.filesystems/nbproject/project.properties Mon Feb 02 10:22:22 2009 +0100 @@ -44,4 +44,4 @@ javadoc.main.page=org/openide/filesystems/doc-files/api.html javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=7.20.0 +spec.version.base=7.21.0 diff -r bd8aef593115 openide.filesystems/src/org/openide/filesystems/FileObject.java --- a/openide.filesystems/src/org/openide/filesystems/FileObject.java Thu Jan 29 17:56:55 2009 +0100 +++ b/openide.filesystems/src/org/openide/filesystems/FileObject.java Mon Feb 02 10:22:22 2009 +0100 @@ -41,23 +41,30 @@ package org.openide.filesystems; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Serializable; import java.net.URL; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; import java.util.StringTokenizer; import org.openide.util.Enumerations; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.UserQuestionException; @@ -161,6 +168,7 @@ * * @return some representation of this file object */ + @Override public String toString() { String cname = getClass().getName(); String cnameShort = cname.substring(cname.lastIndexOf('.') + 1); @@ -502,6 +510,149 @@ * rather than a regular file or is invalid */ public abstract InputStream getInputStream() throws FileNotFoundException; + + /** Reads the full content of the file object and returns it as array of + * bytes. + * @return array of bytes + * @exception IOException in case the content cannot be fully read + * @since 7.21 + */ + public byte[] asBytes() throws IOException { + long len = getSize(); + if (len > Integer.MAX_VALUE) { + throw new IOException("Too big file " + getPath()); // NOI18N + } + InputStream is = getInputStream(); + try { + byte[] arr = new byte[(int)len]; + int pos = 0; + while (pos < arr.length) { + int read = is.read(arr, pos, arr.length - pos); + if (read == -1) { + break; + } + pos += read; + } + if (pos != arr.length) { + throw new IOException("Just " + pos + " bytes read from " + getPath()); // NOI18N + } + return arr; + } finally { + is.close(); + } + } + + /** Reads the full content of the file object and returns it as string. + * @param encoding the encoding to use + * @return string representing the content of the file + * @exception IOException in case the content cannot be fully read + * @since 7.21 + */ + public String asText(String encoding) throws IOException { + return new String(asBytes(), encoding); + } + + /** Reads the full content of the file object and returns it as string. + * This is similar to calling {@link #asText(java.lang.String)} with + * default system encoding. + * + * @return string representing the content of the file + * @exception IOException in case the content cannot be fully read + * @since 7.21 + */ + public String asText() throws IOException { + return asText(Charset.defaultCharset().name()); + } + + /** Reads the full content of the file line by line with default + * system encoding. Typical usage is + * in for loops: + *
+     * for (String line : fo.asLines()) {
+     *   // do something
+     * }
+     * 
+ * @return string representing the content of the file + * @exception IOException in case the content cannot be fully read + * @since 7.21 + */ + public Iterable asLines() throws IOException { + return asLines(Charset.defaultCharset().name()); + } + + /** Reads the full content of the file line by line. Typical usage is + * in for loops: + *
+     * for (String line : fo.asLines("UTF-8")) {
+     *   // do something
+     * }
+     * 
+ * @param encoding the encoding to use + * @return string representing the content of the file + * @exception IOException in case the content cannot be fully read + * @since 7.21 + */ + public Iterable asLines(final String encoding) throws IOException { + class LineIter implements Iterator { + private final BufferedReader reader; + private String line; + + public LineIter() throws IOException { + InputStream is; + if (getSize() < 64 * 1024) { + is = new ByteArrayInputStream(asBytes()); + } else { + is = getInputStream(); + } + reader = new BufferedReader(new InputStreamReader(is, encoding)); + } + + public synchronized boolean hasNext() { + if (line == null) { + try { + line = reader.readLine(); + if (line == null) { + reader.close(); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return line != null; + } + + public synchronized String next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + String l = line; + line = null; + return l; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + return new Iterable() { + LineIter ready = new LineIter(); + + public synchronized Iterator iterator() { + if (ready == null) { + try { + return new LineIter(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + return Collections.emptyList().iterator(); + } + } else { + LineIter li = ready; + ready = null; + return li; + } + } + }; + } /** Get output stream. * @param lock the lock that belongs to this file (obtained by a call to @@ -951,14 +1102,14 @@ } if (fs != null && fsList != null) { for (FileChangeListener fcl : fsList) { - fs.getFCLSupport().dispatchEvent(fcl, fe, op); + FCLSupport.dispatchEvent(fcl, fe, op); } } if (rep != null && repList != null) { for (FileChangeListener fcl : repList) { - rep.getFCLSupport().dispatchEvent(fcl, fe, op); + FCLSupport.dispatchEvent(fcl, fe, op); } } } diff -r bd8aef593115 openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java Thu Jan 29 17:56:55 2009 +0100 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java Mon Feb 02 10:22:22 2009 +0100 @@ -49,6 +49,8 @@ import java.io.*; import java.util.*; import java.net.*; +import java.util.logging.Level; +import java.util.logging.Logger; import org.netbeans.junit.MockServices; import org.netbeans.junit.RandomlyFails; @@ -82,8 +84,10 @@ super(testName); } + @Override protected void setUp() throws java.lang.Exception { MockServices.setServices(); + Logger.getLogger("org.openide.filesystems").setLevel(Level.SEVERE); super.setUp(); @@ -92,6 +96,7 @@ root = fs.findResource(getResourcePrefix()); } + @Override protected void tearDown() throws Exception { super.tearDown(); fs = this.testedFS = null; @@ -118,17 +123,20 @@ class L extends FileChangeAdapter { public int cnt; + @Override public void fileDataCreated(FileEvent fe) { cnt++; } } final FileChangeListener noFileDataCreatedListener = new FileChangeAdapter(){ + @Override public void fileDataCreated(FileEvent fe) { fail(); } }; final FileChangeListener listener1 = new FileChangeAdapter(){ + @Override public void fileDataCreated(FileEvent fe) { try { fold.getFileSystem().removeFileChangeListener(noFileDataCreatedListener); @@ -172,11 +180,13 @@ return; } final FileChangeListener noFileDataCreatedListener = new FileChangeAdapter(){ + @Override public void fileDataCreated(FileEvent fe) { fail(); } }; final FileChangeListener listener1 = new FileChangeAdapter(){ + @Override public void fileDataCreated(FileEvent fe) { fold.removeFileChangeListener(noFileDataCreatedListener); fold.addFileChangeListener(noFileDataCreatedListener); @@ -1543,6 +1553,7 @@ public static void implOfTestGetFileObjectForSubversion(final FileObject folder, final String childName) throws InterruptedException { final List l = new ArrayList(); folder.addFileChangeListener(new FileChangeAdapter(){ + @Override public void fileFolderCreated(FileEvent fe) { l.add(fe.getFile()); synchronized(l) { @@ -1812,6 +1823,97 @@ fsAssert ("After delete should be invalid",!fo1.isValid()); } + public void testAsBytesAndString() throws java.io.FileNotFoundException, IOException { + checkSetUp(); + + FileObject fo1 = getTestFile1 (root); + try { + OutputStream os = fo1.getOutputStream(); + String txt = "Ahoj\nJak\nSe\nMas"; + os.write(txt.getBytes("UTF-8")); + os.close(); + byte[] arr = fo1.asBytes(); + assertNotNull("Arrays is read", arr); + assertEquals("Right length bytes", txt.length(), arr.length); + assertEquals(txt, new String(arr, "UTF-8")); + assertEquals(txt, fo1.asText("UTF-8")); + + int cnt = 0; + for (String l : fo1.asLines("UTF-8")) { + // it is possible to rewrite the content, if the file is small + fo1.getOutputStream().close(); + cnt++; + } + assertEquals("Four lines: " + txt, 4, cnt); + } catch (IOException iex) { + fsAssert ("Expected that FS provides InputStream ",fo1.getSize () == 0); + } + FileLock lock = null; + + try { + lock = fo1.lock (); + fo1.delete(lock); + } catch (IOException iex) { + fsAssert("FileObject shopuld be allowd to be modified.", + fs.isReadOnly() || fo1.isReadOnly()) ; + return; + } finally { + if (lock != null) lock.releaseLock(); + } + fsAssert ("After delete should be invalid",!fo1.isValid()); + } + public void testBigFileAndAsString() throws java.io.FileNotFoundException, IOException { + checkSetUp(); + + FileObject fo1 = getTestFile1 (root); + try { + OutputStream os = fo1.getOutputStream(); + for (int i = 0; i < 10000; i++) { + String txt = "Ahoj\nJak\nSe\nMas\n"; + os.write(txt.getBytes("UTF-8")); + } + os.close(); + if (64 * 1024 > fo1.getSize()) { + fail("We need to generate big file: " + fo1.getSize()); + } + + OutputStream tmp = null; + FileLock lock = null; + int cnt = 0; + int acquire = 3; + for (String l : fo1.asLines("UTF-8")) { + if (cnt % 100 == 0 && acquire-- > 0) { + try { + lock = fo1.lock(); + tmp = fo1.getOutputStream(lock); + tmp.write(0); + fail("The input stream is open for big files. cnt = " + cnt); + } catch (IOException ex) { + // OK + } finally { + lock.releaseLock(); + } + } + cnt++; + } + if (tmp != null) { + tmp.close(); + } + assertEquals("A lot of lines lines: ", 4 * 10000, cnt); + } catch (IOException iex) { + fsAssert ("Expected that FS provides InputStream ",fo1.getSize () == 0); + } + + try { + FileLock lock = fo1.lock (); + fo1.delete(lock); + } catch (IOException iex) { + fsAssert("FileObject shopuld be allowd to be modified.", + fs.isReadOnly() || fo1.isReadOnly()) ; + return; + } + fsAssert ("After delete should be invalid",!fo1.isValid()); + } /** Test of getOutputStream() method, of class org.openide.filesystems.FileObject. */ public void testGetOutputStream() throws java.io.IOException {