[System.Net] Add support for .pac proxy config scripts on mac
[mono.git] / mcs / class / System.Web / System.Web / HttpWriter.cs
1 //
2 // System.Web.HttpWriter.cs 
3 //
4 // 
5 // Author:
6 //      Miguel de Icaza (miguel@novell.com)
7 //
8 //
9 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.IO;
32 using System.Text;
33 using System.Threading;
34 using System.Globalization;
35 using System.Runtime.InteropServices;
36 using System.Security.Permissions;
37         
38 namespace System.Web
39 {       
40         // CAS - no InheritanceDemand here as the class is sealed
41         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
42         public sealed class HttpWriter : TextWriter
43         {
44                 const long MAX_TOTAL_BUFFERS_SIZE = 4 * 1024 * 1024;
45                 const uint SINGLE_BUFFER_SIZE = 128 * 1024;
46                 const uint MIN_SINGLE_BUFFER_SIZE = 32 * 1024;
47                 
48                 HttpResponseStream output_stream;
49                 HttpResponse response;
50                 Encoding encoding;
51
52                 [ThreadStatic]
53                 static byte [] _bytebuffer;
54                 static readonly uint byteBufferSize;
55                 
56                 static HttpWriter ()
57                 {
58                         int workerThreads, completionPortThreads;
59
60                         ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
61                         workerThreads *= 3;
62
63                         uint bufferSize = (uint)(MAX_TOTAL_BUFFERS_SIZE / workerThreads);
64                         byteBufferSize = Math.Min (SINGLE_BUFFER_SIZE, bufferSize);
65                         if (byteBufferSize < MIN_SINGLE_BUFFER_SIZE)
66                                 byteBufferSize = MIN_SINGLE_BUFFER_SIZE;
67                 }
68                 
69                 internal HttpWriter (HttpResponse response)
70                 {
71                         this.response = response;
72                         encoding = response.ContentEncoding;
73                         output_stream = response.output_stream;
74                 }
75
76                 byte [] GetByteBuffer (int length)
77                 {
78                         if (_bytebuffer == null)
79                                 _bytebuffer = new byte [byteBufferSize];
80                         
81                         // We will reuse the buffer if its size is < 32K
82                         if (byteBufferSize >= length)
83                                 return _bytebuffer;
84                         else
85                                 return new byte [length];
86                 }
87
88                 public override Encoding Encoding {
89                         get {
90                                 return encoding;
91                         }
92                 }
93
94                 internal void SetEncoding (Encoding new_encoding)
95                 {
96                         encoding = new_encoding;
97                 }
98
99                 public Stream OutputStream {
100                         get {
101                                 return output_stream;
102                         }
103                 }
104
105                 internal HttpResponse Response {
106                         get { return response; }
107                 }
108                 //
109                 // Flush data, and closes socket
110                 //
111                 public override void Close ()
112                 {
113                         output_stream.Close ();
114                 }
115
116                 public override void Flush ()
117                 {
118                         output_stream.Flush ();
119                 }
120
121                 char [] chars = new char [1];
122                 public override void Write (char ch)
123                 {
124                         chars [0] = ch;
125                         Write (chars, 0, 1);
126                 }
127
128                 public override void Write (object obj)
129                 {
130                         if (obj == null)
131                                 return;
132                         
133                         Write (obj.ToString ());
134                 }
135                 
136                 public override void Write (string s)
137                 {
138                         if (s != null)
139                                 WriteString (s, 0, s.Length);
140                 }
141                 
142                 public override void Write (char [] buffer, int index, int count)
143                 {
144                         if (buffer == null || index < 0 || count < 0 || (buffer.Length - index) < count)
145                                 throw new ArgumentOutOfRangeException ();
146 #if TARGET_JVM
147                         output_stream.Write (buffer, index, count);
148 #else
149                         int length = encoding.GetMaxByteCount (count);
150                         byte [] bytebuffer = GetByteBuffer (length);
151                         int realLength = encoding.GetBytes (buffer, index, count, bytebuffer, 0);
152                         output_stream.Write (bytebuffer, 0, realLength);
153 #endif
154                         if (response.buffer)
155                                 return;
156
157                         response.Flush ();
158                 }
159
160                 static char [] newline = new char [2] { '\r', '\n' };
161                 
162                 public override void WriteLine ()
163                 {
164                         Write (newline, 0, 2);
165                 }
166
167                 public void WriteString (string s, int index, int count)
168                 {
169                         if (s == null)
170                                 return;
171
172                         if (index < 0 || count < 0 || ((index + count > s.Length)))
173                                 throw new ArgumentOutOfRangeException ();
174 #if TARGET_JVM
175                         output_stream.Write (s, index, count);
176 #else
177                         int length = encoding.GetMaxByteCount (count);
178                         byte [] bytebuffer = GetByteBuffer (length);
179                         int realLength = encoding.GetBytes (s, index, count, bytebuffer, 0);
180                         output_stream.Write (bytebuffer, 0, realLength);
181 #endif
182                         if (response.buffer)
183                                 return;
184
185                         response.Flush ();
186                 }
187
188                 internal void WriteUTF8Ptr (IntPtr ptr, int length)
189                 {
190                         output_stream.WritePtr (ptr, length);
191                 }
192
193                 public void WriteBytes (byte [] buffer, int index, int count)
194                 {
195                         output_stream.Write (buffer, index, count);
196
197                         if (response.buffer)
198                                 return;
199
200                         response.Flush ();
201                 }
202         }
203 }
204