Re: [vfs] proposal: FileUtils

2005-02-02 Thread Mario Ivankovits
Hello!
Sorry for being late, but I have had an appointment day with one of our 
customers.

public abstract class Backup implements IOOperation {
protected Backup(final FuPolicy policy) {
And two implementations:
public class NoBackup extends Backup { 
public class SimpleBackup extends Backup { 
The only thing I do not understand is why you need the policy if you 
extend the Backup. The derived classes are the policy.
Else you should do somethink like NoBackupPolicy and SimpleBackupPolicy 
which will be passed to Backup.
But I think extending Backup (to implement different policies) is good 
enough and then you could drop the policy, no?

Ciao,
Mario
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-02 Thread Mario Ivankovits
What do you think, if the commands do not chain the next command, but if 
they create a Undo-Command which will be put on a stack and - in case of 
an exception can be processed to rollback all commands.
I havent though about it in every detail, but if it is possible it is 
easier to handle - and in the case of a file-manager one could provide a 
undo function.

In pseudo code:
UndoStack tx = new UndoStack();
try
{
Backup(tx, ...)
Copy(tx, ...)
Move(tx, ...)
}
catch (Exception)
{
 tx.rollback(); - process undo-stack
}
But again - [transaction] already do something like this. I think I have 
some time today evening to check this out.

Ciao,
Mario
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-02 Thread B. K. Oxley (binkley)
Mario Ivankovits wrote:
In pseudo code:
UndoStack tx = new UndoStack();
try
{
Backup(tx, ...)
Copy(tx, ...)
Move(tx, ...)
}
catch (Exception)
{
 tx.rollback(); - process undo-stack
}
This looks ok.  I still prefer each command to handle it's own cleanup 
(try/catch/finally in part existing for this purpose), but there's 
nothing wrong with the concept.

I'm curious what you find out about Commons Transactions.  When I looked 
 it over, it seemd to me designed with primitives for us to use to make 
our own transactions.  I missed any ready-to-use code for this purpose. 
 I wonder how much overlap there is with java.util.concurrent in the 
new JDK 5.

Cheers,
--binkley
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-02 Thread Mario Ivankovits
Hello!
I'm curious what you find out about Commons Transactions.  When I 
looked  it over, it seemd to me designed with primitives for us to use 
to make our own transactions.  I missed any ready-to-use code for this 
purpose.  I wonder how much overlap there is with java.util.concurrent 
in the new JDK 5.
On their homepage they state they have done this for a java.io.File 
implementation.
JDK5: Dont forget, our target is jdk1.3 (even if I use 1.5 since it is 
out) You cant imagine how fast the first user shouted after I used (by 
mistake) a jdk 1.4 method.

---
Mario
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-02 Thread B. K. Oxley (binkley)
Mario Ivankovits wrote:
JDK5: Dont forget, our target is jdk1.3 (even if I use 1.5 since it is 
out) You cant imagine how fast the first user shouted after I used (by 
mistake) a jdk 1.4 method.
JDK 1.3!?  I had no earthly idea.
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-02 Thread Mario Ivankovits
B. K. Oxley (binkley) wrote:
I'm curious what you find out about Commons Transactions.  When I 
looked  it over, it seemd to me designed with primitives for us to use 
to make our own transactions.  I missed any ready-to-use code for this 
purpose. 
After 2 hours of copy/paste their FileResourceManager to use 
vfs.FileObject only I am able to do such thing:

// init phase
   String tx1 = tx1;
   VFSResourceManager rsm = new VFSResourceManager(
   VFS.getManager(),
   /home/im/tmp/tx/store, // = root filesystem where the 
real stuff should happen on commit
   /home/im/tmp/tx/work, // = work filesystem - could be 
different to store above
   new PrintWriterLogger(new PrintWriter(System.err), VFS, true),
   true
   );
   rsm.start();
// start transaction
   rsm.startTransaction(tx1);
// create file1
   rsm.createResource(tx1, dir1/file1.txt);
// create file2
   rsm.createResource(tx1, dir2/file1.txt);
// write into file1
   OutputStream os = rsm.writeResource(tx1, dir1/file1.txt);
   os.write(test.getBytes());
   os.close();
// delete file2
   rsm.deleteResource(tx1, dir2/file1.txt);
   rsm.deleteResource(tx1, dir2); // = dir2 has been created by 
the above createResource - now we have to remove it here manually.
// commit transaction
   rsm.commitTransaction(tx1);

Now - whats missing in this example?  right  there is no move 
or rename operation.

Summary:
*) implement rename
*) implement something like listResource(tx) where we could get a list 
of all files in an directory - including/excluding those created/deleted 
within the transation.
Both need some more investigation to see how this could happen.

After experimenting a little bit it is fantastic to see who it prevents 
two simultan transactions to create the same file - in fact it isnt 
prevent - the second transaction just waits until the first has finished 
and then the second gains the lock.
So we get in-process locking for free.
The above code is just a start, but think of a file-object where the 
transactional logic is encapsulated and one can do whatever he wants - 
it will only be represented on the filesystem if commit() has been called.

FileObject foRootTransactional = VFS.getManager().beginTransaction(foRoot)
for (child .. foRootTransactional.getChildren())
{
   child.delete();
}
VFS.getManager().commitTransaction(foRootTransactional);
And maybe if your RamFS comes to reality we could use it as work-space 
e.g. if we know we handle only small transactions.

I am looking forward to read what you think about it.
If you would like to experiment a little bit follow the instructions at 
http://l3x.net/imwiki/Wiki.jsp?page=VfsStuff

---
Mario
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-02-01 Thread B. K. Oxley (binkley)
Continuing the command pattern, I rejiggered the Save command to use a 
Backup command rather than hard-coding the backup policy:

public class Save implements IOOperation {
private final Backup backup;
private final InputStream newContents;
private final FuFile original;
public Save(final Backup backup, final InputStream newContents,
final FuFile original) {
if (null == backup) throw new NullPointerException();
if (null == newContents) throw new NullPointerException();
if (null == original) throw new NullPointerException();
this.backup = backup;
this.newContents = newContents;
this.original = original;
}
public void execute()
throws IOException {
backup.prepare(original,
new Write(newContents, original)).execute();
}
}
Notice the prepare method which is an example of delayed 
initialization.  Since Backup needs a next operation, but Save both 
needs a Backup and creates the next operation (a Write command), I 
cannot both create an immutable Backup and create an immutable Save at 
the same time.

And looking at Backup:
public abstract class Backup implements IOOperation {
protected final FuPolicy policy;
private FuFile original;
private IOOperation next;
protected Backup(final FuPolicy policy) {
if (null == policy) throw new NullPointerException();
this.policy = policy;
}
protected FuFile getOriginal() {
return original;
}
protected IOOperation getNext() {
return next;
}
public Backup prepare(final FuFile original, final IOOperation next) {
if (null == original) throw new NullPointerException();
if (null == next) throw new NullPointerException();
this.original = original;
this.next = next;
return this;
}
}
And two implementations:
public class NoBackup extends Backup {
public NoBackup(final FuPolicy policy) {
super(policy);
}
public void execute()
throws IOException {
final FuFile original = getOriginal();
new Delete(original, policy.createScratch(original), 
getNext()).execute();
}
}

public class SimpleBackup extends Backup {
public SimpleBackup(final FuPolicy policy) {
super(policy);
}
public void execute()
throws IOException {
final FuFile original = getOriginal();
final FuFile backup = policy.createBackup(original);
new Delete(backup, policy.createScratch(backup),
new Move(original, backup, getNext())).execute();
}
}
The second implementation, SimpleBackup, implements the policy 
hard-coded previously in Save.

I still use the FuPolicy object to decide how to make a temporary and a 
backup file.  I think that creating a backup should be merged into the 
Backup object instead, but I haven't decided what the best way to do 
that is.  The problem scenario is an Emacs-scheme multiple backup (e.g., 
foo.txt, foo.txt.~1~, foo.txt.~2~, etc.).  There the policy for naming 
backups and the backup command are very intimate, and really belong in 
the same object.

Cheers,
--binkley
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-31 Thread B. K. Oxley (binkley)
Mario Ivankovits wrote:
Where do you think to implement this FileOperation interface? I miss
 the source fileobject -a s I said, I dont want to implement the 
interface in the FileObject and thus thought about something like 
this:

DefaultFileOperations.get().copy(FileObject src, FileObject dest);
I was going to pass the src in on construction of the operation object,
but why?  Using src as part of the parameter list seems just as good.
void save(final OutputStream newContents, final FileObject dest, 
final boolean overwrite) throws FileSystemException;
I have a strong distaste for using flags to control behavior in public
methods.  I find that it often leads to bugs when the flags are wrong,
and it makes understanding the code more difficult.  That is why I
prefer explicitly named methods:
void save(final OutputStream newContents, final FileObject dest) throws
FileSystemException;
void saveAndOverwrite(final OutputStream newContents, final FileObject
dest) throws FileSystemException;
How strong is your preference?
If overwrite=false and the destination exists the methods should use 
backup() to create a backup of the destination file
As an alternative, I took someone's suggestion of a policy object when I
started coding a default implementation of the FileOperation interface,
and let the policy object figure these things out.
Another thing we could discuss is the usage of save(InputStream,
...). I renamed it to copy(InputStream, ...). I think if you do have
an InputStream you would like to copy its output to another file - in
opposite to save(OutputStream ...) where you do have the content of
the file in memory (a bufferedImage, ) and would like to save
it.
I like save() because it describes the operation most closely from the 
point of view of the caller (Hey, save this file with these new 
contents!).  The reason I used InputStream everywhere was for 
genericness (is that a word?).  I pictured usage like this:

// copy(src, dst) in your snippet
operations.save(src, otherFile.getInputStream());
operations.save(src, new ByteArrayInputStream(blobInMemory.toArray());
This sort of negotiation over interface is painful remotely.  I'd 
rather do it with my programming pairmate while writing unit tests.  :-)

Cheers,
--binkley
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-31 Thread Mario Ivankovits
Hello!
void save(final OutputStream newContents, final FileObject dest) throws
FileSystemException;
void saveAndOverwrite(final OutputStream newContents, final FileObject
dest) throws FileSystemException;
How strong is your preference?
Doesnt lead such a design to have tons of saveAnd methods. And the 
code within those objects is highly redundant, isnt it?
However, I will let this decision on you. I never tried this style, 
maybe it become accepted.

If overwrite=false and the destination exists the methods should use 
backup() to create a backup of the destination file
As an alternative, I took someone's suggestion of a policy object when I
started coding a default implementation of the FileOperation interface,
and let the policy object figure these things out.
;-) Wasnt it me? I wanted you to use a BackupPolicy. And yes - I think 
this is the cleanest solution. I just thought you didnt want to go this 
way now as I missed it in your latest proposal.
If you already took this way it is even better.

I like save() because it describes the operation most closely from the 
point of view of the caller (Hey, save this file with these new 
contents!).  The reason I used InputStream everywhere was for 
genericness (is that a word?).  I pictured usage like this:
You ask me? A non native speaker. However, it sounds cool ;-))
// copy(src, dst) in your snippet
operations.save(src, otherFile.getInputStream());
operations.save(src, new ByteArrayInputStream(blobInMemory.toArray());
Didnt you mean?
operations.save(otherFile.getInputStream(), dest);
operations.save(new ByteArrayInputStream(blobInMemory.toArray()), dest);
But every Filesystem call it copy and even if you use a file-manager 
there is a menu-entry called copy. save or save As only exists if 
you do have the content of the file open in an editor - and then, from 
the point of development - it is easier if the save method took an 
outputStream.

---
Mario



smime.p7s
Description: S/MIME Cryptographic Signature


Re: [vfs] proposal: FileUtils

2005-01-31 Thread B. K. Oxley (binkley)
I looked over the problem again and think I'd prefer a command object 
approach:

public interface OperationE extends Exception {
void execute() throws E;
}
And:
public interface IOOperation extends OperationIOException { }
(Excess abstraction, I know.  I had a hard time resisting the coolness 
of generic exceptions.)

And some operations:
public class Move implements IOOperation {
private final FuFile original, newLocation;
private final IOOperation next;
public Move(final FuFile original, final FuFile newLocation,
final IOOperation next) {
if (null == original) throw new NullPointerException();
if (null == newLocation) throw new NullPointerException();
if (null == next) throw new NullPointerException();
this.original = original;
this.newLocation = newLocation;
this.next = next;
}
public void execute()
throws IOException {
original.moveTo(newLocation);
try {
next.execute();
} catch (final IOException e) {
newLocation.moveTo(original);
throw e;
}
}
}
And to make a Save operation:
public class Save implements IOOperation {
private final FuPolicy policy;
private final InputStream newContents;
private final FuFile original;
public Save(final FuPolicy policy, final InputStream newContents,
final FuFile original) {
if (null == policy) throw new NullPointerException();
if (null == newContents) throw new NullPointerException();
if (null == original) throw new NullPointerException();
this.policy = policy;
this.newContents = newContents;
this.original = original;
}
public void execute()
throws IOException {
final FuFile backup = policy.createBackup(original);
new Delete(backup, policy.createScratch(backup),
new Move(original, backup,
new Write(newContents, original))).execute();
}
}
Isn't that nifty?  :-)
I get to use the policy object without interfering with FuFile (my 
dummy file object just for proof of concept); I can create complex 
operations by composing simpler operations as building blocks.

In fact, perhaps I should pull new Delete(...), new Move(...) and 
new Write(...) out into fields of Save so that someone could replace 
them with subclassed instances via IoC.

How does that suit you?
Cheers,
--binkley
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-30 Thread B. K. Oxley (binkley)
How is this for an interface for file operations?
public interface FileOperation {
void save(final InputStream newContents)
throws FileSystemException;
void saveAndBackup(final InputStream newContents)
throws FileSystemException;
void copyTo(final FileName newLocation)
throws FileSystemException;
void copyToAndOverwrite(final FileName newLocation)
throws FileSystemException;
void moveTo(final FileName newLocation)
throws FileSystemException;
void moveToAndOverwrite(final FileName newLocation)
throws FileSystemException;
}
I think this covers 80%+ of use cases.  This is your classic 
cut/copy/paste operations with a file manager and the usual file-saving 
operation of an editor.

Cheers,
--binkley
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-30 Thread Mario Ivankovits
Hello!
How is this for an interface for file operations?
Where do you think to implement this FileOperation interface?
I miss the source fileobject -a s I said, I dont want to implement the 
interface in the FileObject and thus thought about something like this:

DefaultFileOperations.get().copy(FileObject src, FileObject dest);
or - if you use your own (derived) implementation:
FileOperations fops = new MyFileOperations(); // this has to be done 
only once for the whole application
fops.copy(FileObject src, FileObject dest);

public interface FileOperation
{
   void save(final OutputStream newContents, final FileObject dest, 
final boolean overwrite) throws FileSystemException;
   void copy(final InputStream src, final FileObject dest, final 
boolean overwrite) throws FileSystemException;
   void copy(final FileObject src, final FileObject dest, final boolean 
overwrite) throws FileSystemException;
   void move(final FileObject src, final FileObject dest, final boolean 
overwrite) throws FileSystemException;
   void backup(final FileObject file) throws FileSystemException;
}

If overwrite=false and the destination exists the methods should use 
backup() to create a backup of the destination file

Another thing we could discuss is the usage of save(InputStream, ...). I 
renamed it to copy(InputStream, ...). I think if you do have an 
InputStream you would like to copy its output to another file - in 
opposite to save(OutputStream ...) where you do have the content of the 
file in memory (a bufferedImage, ) and would like to save it.
In this case the save(OutputStream ...) should write the content to a 
temporary file and later use move() to put it on its right place.

What do you think about this?
Ciao,
Mario
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-25 Thread Mario Ivankovits
Hi Brian!
Sorry for the long delay. I was in an delivery period and therefore out 
of time.

After the next week I should have more time again.
I am not sure we should implement a poor-man's transaction if we could 
have more ([transaction] ) for free.
Hmmm, I would like to have a depper look on this, remind, if 
[transaction] fits our needs, we might have locking too.

Please let us delay this decision for a while, before we do the hard 
work I would like to see myself that [transaction] is really overkill.

Thanks!
---
Mario


smime.p7s
Description: S/MIME Cryptographic Signature


Re: [vfs] proposal: FileUtils

2005-01-21 Thread Mario Ivankovits
Damn good work!
I think we should introduce a FileUtils class, I dont want to bloat the 
FileObject with utility functions.

About transactionality :- care should be taken to not reimplement 
something like [transaction], they already implemented such a beast 
using java.io.File. Maybe we can adopt it.

So my FileUtils would look like this:
public class FileUtils
{
   void copy(InputStream is, FileObject fo) throws FuException;
   void copy(FileObject input, FileObject new) throws FuException;
   void copy(FileObject fo, OutputStream out) throws FuException;
   void copy(InputStream is, FileObject fo, BackupStrategy bs) throws 
FuException;
   void copy(FileObject input, FileObject new, BackupStrategy bs) 
throws FuException;

   void move(FileObject old, FileObject new) throws FuException;
   void move(FileObject old, FileObject new, BackupStrategy bs) throws 
FuException;

   void append(FileObject input, FileObject new) throws FuException;
   void append(InputStream is, FileObject new) throws FuException;
   void append(FileObject input, FileObject new, BackupStrategy bs) 
throws FuException;
   void append(InputStream is, FileObject new, BackupStrategy bs) 
throws FuException;

   void delete(FileObject fo) throws FuException;

}
public interface BackupStrategy
{
  /**
 * Takes the fileObject and moves it away.
 * returns the new file or null if the file has been deleted. (e.g. 
file overwrite)
 */
   FileObject createBackup(FileObject fileObject) throws FuException;
}

Thanks!
---
Mario
PS: isnt throw (IOException) new IOException().initCause(e); what you 
searched?

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [vfs] proposal: FileUtils

2005-01-21 Thread B. K. Oxley (binkley)
Mario Ivankovits wrote:
About transactionality :- care should be taken to not reimplement 
something like [transaction], they already implemented such a beast 
using java.io.File. Maybe we can adopt it.
I'll have to look at it, but it looked like overkill for what I had in mind.
I've been toying with closure-like operations to take care of this, so 
that saving from an input stream with a backup looks like:

FuFile newContent = new FuFile(newContentStream);
new Move(backup, backup.createTemporary(),
new Move(original, backup,
new Move(newContent, original, Noop)))
The bulk of Move is:
public void eval() throws FuException {
try {
original.moveTo(newLocation);
nextMoveClosure.eval();
} catch (FuException e) {
newLocation.moveTo(original);
throw e;
}
}
This means that you try to rename the original, call the next operation 
and if that fails, undo the rename.  It's a poor-man's transaction.

If you look at the nesting of my first code snippet, it behaves like this:
1. Write the content to a temporary.
2. Move the backup to a temporary to recover the backup if other 
operations fail.
3. Move the original to the backup to recover the original if other 
operations fail.
4. Move the content temporary to the original.

The only complication I didn't mention is that my actual code takes care 
of deleting the various temporaries when things fail or they don't.

Another way to view this is that I took:
try {
doTryWork();
} catch (e) {
doCatchWork();
throw e;
} finally {
doFinallyWork();
}
And made each of the do work methods a closure object with an eval() 
method to invoke them.

Cheers,
Brian
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]