On Thu, 29 Jun 2006, Charles O Nutter defenestrated me:
> 
>    Whee!

  I needed to do a surprising additional number of things to 
get rails silence_stderr working with this patch.  Here is a break-
down:

1. reopen with string as first arg should retain permissions/modes
   of IO it is reopening.  I believe this has to be right.
2. dup should retain dup'd objects permissions/modes.  This also
   seems like a for sure thing.
3. reopen needed same /dev/null check that RubyFile has in reopen.
   As hacky as hacky gets.
4. IOHandlerUnseekable now refuses to close System.out and System.err.
   This is also a hack.  The solution involves much too much stuff
   to be safe right now.  Really a io.dup should clone the underlying
   IOHandler.  If multiple IO's point to same underlying stream
   then a close should not really close the underlying stream.
   I believe this is consistent with C FILE* and friends (C Ruby
   semantics I think rely on FILE* and friends)?  

  Please look this over.  I would like to include this for 0.9.0 
since it makes Rails commands that perform command checks work without
needing to patch Rails.

-Tom

-- 
+ http://www.tc.umn.edu/~enebo +---- mailto:[EMAIL PROTECTED] ----+
| Thomas E Enebo, Protagonist  | "Luck favors the prepared    |
|                              |  mind." -Louis Pasteur       |
Index: org/jruby/RubyFile.java

===================================================================

RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyFile.java,v

retrieving revision 1.40

diff -u -r1.40 RubyFile.java

--- org/jruby/RubyFile.java     30 May 2006 17:52:48 -0000      1.40

+++ org/jruby/RubyFile.java     30 Jun 2006 02:59:35 -0000

@@ -44,6 +44,7 @@

 import org.jruby.exceptions.RaiseException;

 import org.jruby.runtime.builtin.IRubyObject;

 import org.jruby.util.IOHandler;

+import org.jruby.util.IOHandlerNull;

 import org.jruby.util.IOHandlerSeekable;

 import org.jruby.util.IOHandlerUnseekable;

 import org.jruby.util.IOModes;

@@ -105,9 +106,13 @@

     public void openInternal(String newPath, IOModes newModes) {

         this.path = newPath;

         this.modes = newModes;

-

+        

         try {

-            handler = new IOHandlerSeekable(getRuntime(), newPath, newModes);

+            if (newPath.equals("/dev/null")) {

+                handler = new IOHandlerNull(getRuntime(), newModes);

+            } else {

+                handler = new IOHandlerSeekable(getRuntime(), newPath, 
newModes);

+            }

             

             registerIOHandler(handler);

         } catch (InvalidValueException e) {

Index: org/jruby/RubyIO.java

===================================================================

RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyIO.java,v

retrieving revision 1.55

diff -u -r1.55 RubyIO.java

--- org/jruby/RubyIO.java       28 Jun 2006 02:25:51 -0000      1.55

+++ org/jruby/RubyIO.java       30 Jun 2006 02:59:37 -0000

@@ -45,6 +45,7 @@

 import org.jruby.util.IOHandler;

 import org.jruby.util.IOHandlerJavaIO;

 import org.jruby.util.IOHandlerNio;

+import org.jruby.util.IOHandlerNull;

 import org.jruby.util.IOHandlerProcess;

 import org.jruby.util.IOHandlerSeekable;

 import org.jruby.util.IOHandlerUnseekable;

@@ -333,21 +334,29 @@

             registerIOHandler(handler);

         } else if (args[0].isKindOf(getRuntime().getClass("String"))) {

             String path = ((RubyString) args[0]).toString();

-            String mode = "r";

+            IOModes newModes = null;

+

             if (args.length > 1) {

                 if (!args[1].isKindOf(getRuntime().getClass("String"))) {

                     throw getRuntime().newTypeError(args[1], 
getRuntime().getClass("String"));

                 }

                     

-                mode = ((RubyString) args[1]).toString();

+                newModes = new IOModes(getRuntime(), ((RubyString) 
args[1]).toString());

             }

 

             try {

                 if (handler != null) {

                     close();

                 }

-                modes = new IOModes(getRuntime(), mode);

-                handler = new IOHandlerSeekable(getRuntime(), path, modes);

+

+                if (newModes != null) {

+                       modes = newModes;

+                }

+                if ("/dev/null".equals(path)) {

+                       handler = new IOHandlerNull(getRuntime(), modes);

+                } else {

+                       handler = new IOHandlerSeekable(getRuntime(), path, 
modes);

+                }

                 

                 registerIOHandler(handler);

             } catch (IOHandler.InvalidValueException e) {

@@ -743,6 +752,7 @@

         // copy of the handler.  In fact, ruby 1.8 must do this as the cloned

         // resource is in fact a different fileno.  What is clone for again?

         io.handler = handler;

+        io.modes = (IOModes) modes.clone();

         

         return io;

     }

Index: org/jruby/util/IOHandlerUnseekable.java

===================================================================

RCS file: /cvsroot/jruby/jruby/src/org/jruby/util/IOHandlerUnseekable.java,v

retrieving revision 1.16

diff -u -r1.16 IOHandlerUnseekable.java

--- org/jruby/util/IOHandlerUnseekable.java     24 May 2006 01:34:04 -0000      
1.16

+++ org/jruby/util/IOHandlerUnseekable.java     30 Jun 2006 02:59:38 -0000

@@ -163,7 +163,15 @@

         }

         

         if (modes.isWriteable()) {

-            output.close();

+               // Fixme: Only close underlying stream if it is not shared by 
another IO.

+               // HACK: We do not close these streams so that Rails 
silence_stderr will work.

+               //  The real problem is that when silense_stderr clones STDERR, 
we do not actually

+               //  clone the handler AND get a new fileno.  The importance of 
this is coupled

+               //  with the above Fixme, that we need to make sure we only 
close underlying streams

+               //  that are not shared by multiple IOHandlers (at least I 
believe this to be true).

+               if (output != System.out && output != System.err) {

+                       output.close();

+               }

         }

     }

 

Index: org/jruby/util/IOModes.java

===================================================================

RCS file: /cvsroot/jruby/jruby/src/org/jruby/util/IOModes.java,v

retrieving revision 1.11

diff -u -r1.11 IOModes.java

--- org/jruby/util/IOModes.java 22 Jun 2006 02:11:16 -0000      1.11

+++ org/jruby/util/IOModes.java 30 Jun 2006 02:59:38 -0000

@@ -56,6 +56,10 @@

         this.runtime = runtime;

     }

     

+    public Object clone() {

+       return new IOModes(runtime, modes);

+    }

+    

     public IOModes(IRuby runtime, String modesString) {

        this(runtime, convertModesStringToModesInt(runtime, modesString));

     }

Index: org/jruby/util/IOHandlerNull.java

===================================================================

RCS file: org/jruby/util/IOHandlerNull.java

diff -N org/jruby/util/IOHandlerNull.java

--- /dev/null   1 Jan 1970 00:00:00 -0000

+++ org/jruby/util/IOHandlerNull.java   1 Jan 1970 00:00:00 -0000

@@ -0,0 +1,101 @@

+package org.jruby.util;

+

+import java.io.EOFException;

+import java.io.IOException;

+import java.nio.channels.FileChannel;

+

+import org.jruby.IRuby;

+

+public class IOHandlerNull extends IOHandler {

+    

+    public IOHandlerNull(IRuby runtime, IOModes modes) {

+        super(runtime);

+        

+        this.modes = modes;

+    }

+

+    public FileChannel getFileChannel() {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+    public String gets(String separatorString) throws IOException,

+            BadDescriptorException, EOFException {

+        throw new EOFException();

+    }

+

+    public String getsEntireStream() throws IOException,

+            BadDescriptorException, EOFException {

+        throw new EOFException();

+    }

+

+    public String read(int number) throws IOException, BadDescriptorException,

+            EOFException {

+        throw new EOFException();

+    }

+

+    public int write(String string) throws IOException, BadDescriptorException 
{

+        return string.length();

+    }

+

+    public int getc() throws IOException, BadDescriptorException, EOFException 
{

+        throw new EOFException();

+    }

+

+    public void ungetc(int c) {

+    }

+

+    public void putc(int c) throws IOException, BadDescriptorException {

+    }

+

+    public String sysread(int number) throws IOException,

+            BadDescriptorException, EOFException {

+        throw new EOFException();

+    }

+

+    public int syswrite(String buf) throws IOException, BadDescriptorException 
{

+        return buf.length();

+    }

+

+    public IOHandler cloneIOHandler() throws IOException, PipeException,

+            InvalidValueException {

+        return null;

+    }

+

+    public void close() throws IOException, BadDescriptorException {

+    }

+

+    public void flush() throws IOException, BadDescriptorException {

+    }

+

+    public void sync() throws IOException, BadDescriptorException {

+    }

+

+    public boolean isEOF() throws IOException, BadDescriptorException {

+        return true;

+    }

+

+    public int pid() {

+        return 0;

+    }

+

+    public long pos() throws IOException, PipeException {

+        return 0;

+    }

+

+    protected void resetByModes(IOModes newModes) throws IOException,

+            InvalidValueException {

+    }

+

+    public void rewind() throws IOException, PipeException,

+            InvalidValueException {

+    }

+

+    public void seek(long offset, int type) throws IOException, PipeException,

+            InvalidValueException {

+    }

+

+    public void truncate(long newLength) throws IOException, PipeException {

+    }

+

+}

Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel

Reply via email to