2008-04-23 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpWriter.cs
index 3366a45d753a4c057091aa7499da1db433c0b597..4b608d16ef7f78c6eb2b6a38154173be56ecee28 100644 (file)
@@ -1,10 +1,12 @@
-// 
-// System.Web.HttpWriter
 //
+// System.Web.HttpWriter.cs 
+//
+// 
 // Author:
-//   Patrik Torstensson (Patrik.Torstensson@labs2.com)
+//     Miguel de Icaza (miguel@novell.com)
 //
-
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-using System;
+
 using System.IO;
 using System.Text;
-using System.Web.Util;
-
-namespace System.Web
-{
-       public sealed class HttpWriter : TextWriter
-       {
-               internal const int MaxBufferSize = 32768;
-               
-               HttpResponse _Response;
-
-               HttpResponseStream _ResponseStream;
-
-               MemoryStream _OutputStream;
-               StreamWriter _OutputHelper;
-               Encoding _Encoding;     
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+       
+namespace System.Web {
+       
+       // CAS - no InheritanceDemand here as the class is sealed
+       [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+       public sealed class HttpWriter : TextWriter {
+               HttpResponseStream output_stream;
+               HttpResponse response;
+               Encoding encoding;
+               byte [] _bytebuffer = new byte [1024];
 
-               Stream _OutputFilter;
-               HttpResponseStreamProxy _OutputProxy;
-
-               internal HttpWriter (HttpResponse Response)
+               internal HttpWriter (HttpResponse response)
                {
-                       _Response = Response;
-
-                       _Encoding = _Response.ContentEncoding;
-                       _OutputStream = new MemoryStream (MaxBufferSize);
-                       _OutputHelper = new StreamWriter (_OutputStream, _Response.ContentEncoding);
-                       _ResponseStream = new HttpResponseStream (this);
-               }  
-
-               internal void Dispose ()
-               {
-                       _OutputHelper.Close ();
-                       _OutputStream.Close ();
-                       _OutputFilter.Close ();
+                       this.response = response;
+                       encoding = response.ContentEncoding;
+                       output_stream = response.output_stream;
                }
 
-               internal Stream GetActiveFilter ()
+               byte [] GetByteBuffer (int length)
                {
-                       if (null == _OutputFilter) {
-                               // Create a filter proxy to allow us to know if we have a valid filter
-                               if (null == _OutputProxy)
-                                       _OutputProxy = new HttpResponseStreamProxy (this);
+                       // We will reuse the buffer if its size is < 32K
+                       if (_bytebuffer.Length >= length)
+                               return _bytebuffer;
 
-                               return _OutputProxy;
-                       }
-                       return _OutputFilter;
-               }
-
-               internal void ActivateFilter (Stream OutputFilter)
-               {
-                       if (null == _OutputProxy)
-                               throw new HttpException ("Invalid filter usage");
+                       if (length > 32 * 1024)
+                               return new byte [length];
 
-                       _OutputFilter = OutputFilter;
+                       _bytebuffer = new byte [length];
+                       return _bytebuffer;
                }
 
-               internal void FilterData (bool CloseStream)
-               {
-                       // Check if we have any filter at all
-                       if (null == _OutputFilter)
-                               return;
-
-                       FlushBuffers ();
-
-                       // Save our current data
-                       byte [] arrData = _OutputStream.GetBuffer ();
-                       int size = (int) _OutputStream.Length;
-
-                       // Remove our internal data
-                       Clear ();
-
-                       // If we have a filter then we have a proxy
-                       _OutputProxy.Active = true;
-
-                       try {
-                               // Call the filter (it does a callback into our HttpWriter again)
-                               _OutputFilter.Write (arrData, 0, size);
-                               _OutputFilter.Flush ();
-
-                               if (CloseStream)
-                                       _OutputFilter.Close ();
-                       } finally {
-                               _OutputProxy.Active = false;
-                       }
-               }
-
-               internal void Clear ()
-               {
-                       // This clears all the buffers that are around
-                       _OutputHelper.Flush ();
-                       _OutputStream.SetLength (0);
-               }
-
-               internal void SendContent (HttpWorkerRequest Handler)
-               {
-                       FlushBuffers();
-
-                       int l = (int)_OutputStream.Length;
-                       if (l > 0) {
-                               byte [] arrContent = _OutputStream.GetBuffer ();
-                               Handler.SendResponseFromMemory (arrContent, l);
+               public override Encoding Encoding {
+                       get {
+                               return encoding;
                        }
                }
 
-               internal void Update ()
+               internal void SetEncoding (Encoding new_encoding)
                {
-                       _Encoding = _Response.ContentEncoding;
-                       _OutputHelper.Flush ();
-                       _OutputHelper = new StreamWriter (_OutputStream, _Encoding);
+                       encoding = new_encoding;
                }
 
-               internal long BufferSize
-               {
+               public Stream OutputStream {
                        get {
-                               FlushBuffers ();
-                               return _OutputStream.Length;
+                               return output_stream;
                        }
                }
 
-               internal void FlushBuffers ()
-               {
-                       _OutputHelper.Flush ();
-                       _OutputStream.Flush ();
-               }
-
-               internal byte[] GetBuffer () {
-                       return _OutputStream.GetBuffer ();
-               }
-               
-               public override Encoding Encoding
-               {
-                       get { return _Encoding; }
-               }
-
-               public Stream OutputStream
-               {
-                       get { return _ResponseStream; }
-               }
-
+               //
+               // Flush data, and closes socket
+               //
                public override void Close ()
                {
-                       _Response.Flush ();
-                       _Response.Close ();
+                       output_stream.Close ();
                }
 
                public override void Flush ()
                {
+                       output_stream.Flush ();
                }
 
-               private void CheckIfFlush ()
-               {
-                       if (!_Response.BufferOutput) {
-                               FlushBuffers ();
-                       }
-               }
-
+               char [] chars = new char [1];
                public override void Write (char ch)
                {
-                       _OutputHelper.Write (ch);
-                       CheckIfFlush ();
+                       chars [0] = ch;
+                       Write (chars, 0, 1);
                }
 
                public override void Write (object obj)
                {
-                       if (obj != null)
-                       {
-                               _OutputHelper.Write (obj.ToString ());
-                               CheckIfFlush ();
-                       }
+                       if (obj == null)
+                               return;
+                       
+                       Write (obj.ToString ());
                }
-
+               
                public override void Write (string s)
                {
-                       _OutputHelper.Write (s);
-                       CheckIfFlush ();
+                       if (s != null)
+                               WriteString (s, 0, s.Length);
                }
-
+               
                public override void Write (char [] buffer, int index, int count)
                {
-                       _OutputHelper.Write (buffer, index, count);
-                       CheckIfFlush ();
-               }
+                       if (buffer == null || index < 0 || count < 0 || (buffer.Length - index) < count)
+                               throw new ArgumentOutOfRangeException ();
+#if TARGET_JVM
+                       output_stream.Write (buffer, index, count);
+#else
+                       int length = encoding.GetMaxByteCount (count);
+                       byte [] bytebuffer = GetByteBuffer (length);
+                       int realLength = encoding.GetBytes (buffer, index, count, bytebuffer, 0);
+                       output_stream.Write (bytebuffer, 0, realLength);
+#endif
+                       if (response.buffer)
+                               return;
 
-               public void WriteBytes (byte [] buffer, int index, int count)
-               {
-                       _OutputStream.Write (buffer, index, count);
-                       CheckIfFlush ();
+                       response.Flush ();
                }
 
+               static char [] newline = new char [2] { '\r', '\n' };
+               
                public override void WriteLine ()
                {
-                       _OutputHelper.Write ("\r\n");
-                       CheckIfFlush ();
+                       Write (newline, 0, 2);
                }
 
                public void WriteString (string s, int index, int count)
                {
-                       _OutputHelper.Write (s.Substring (index, count));
-                       CheckIfFlush ();
+                       if (s == null)
+                               return;
+
+                       if (index < 0 || count < 0 || ((index + count > s.Length)))
+                               throw new ArgumentOutOfRangeException ();
+#if TARGET_JVM
+                       output_stream.Write (s, index, count);
+#else
+                       int length = encoding.GetMaxByteCount (count);
+                       byte [] bytebuffer = GetByteBuffer (length);
+                       int realLength = encoding.GetBytes (s, index, count, bytebuffer, 0);
+                       output_stream.Write (bytebuffer, 0, realLength);
+#endif
+                       if (response.buffer)
+                               return;
+
+                       response.Flush ();
+               }
+
+               public void WriteBytes (byte [] buffer, int index, int count)
+               {
+                       output_stream.Write (buffer, index, count);
+
+                       if (response.buffer)
+                               return;
+
+                       response.Flush ();
                }
        }
 }