fixed tests
[mono.git] / mcs / class / Mainsoft.Web / Mainsoft.Web.Hosting / ServletWorkerRequest.jvm.cs
1 //
2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
3 //
4
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25 using System;
26 using System.IO;
27 using System.Text;
28 using System.Runtime.InteropServices;
29 using System.Web.Util;
30 using System.Web.J2EE;
31 using System.Collections;
32 using System.Web;
33 using javax.servlet;
34 using javax.servlet.http;
35 using System.Collections.Specialized;
36 using System.Globalization;
37 using System.Web.Hosting;
38 using vmw.common;
39 using vmw.@internal.j2ee;
40 using InputStream=java.io.InputStream;
41
42 namespace Mainsoft.Web.Hosting {
43         [MonoTODO("Implement security demands on the path usage functions (and review)")]
44         [ComVisible (false)]
45         internal sealed class ServletWorkerRequest : HttpWorkerRequest, IServiceProvider {
46                 readonly HttpServlet _HttpServlet;
47                 readonly HttpServletRequest _HttpServletRequest;
48                 readonly HttpServletResponse _HttpServletResponse;
49                 java.io.OutputStream _OutputStream;
50
51                 readonly string _requestUri;
52                 readonly string _pathInfo;
53
54                 static readonly StringDictionary _srvVarsToHeaderMap;
55
56                 private string [][] unknownHeaders;
57                 string _rawUrl;
58
59                 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
60                 private object _endOfSendArgs;
61
62                 enum KnownServerVariable {
63                         AUTH_TYPE,
64                         CONTENT_LENGTH,
65                         CONTENT_TYPE,
66                         QUERY_STRING,
67                         REMOTE_ADDR,
68                         REMOTE_HOST,
69                         REMOTE_USER,
70                         REQUEST_METHOD,
71                         REQUEST_URI,
72                         SCRIPT_NAME,
73                         SERVER_NAME,
74                         SERVER_PORT,
75                         SERVER_PROTOCOL,
76                         SERVER_SOFTWARE,
77                         PATH_INFO
78                 };
79
80                 static readonly Hashtable KnownServerVariableMap;
81
82                 static ServletWorkerRequest() {
83                         _srvVarsToHeaderMap = new StringDictionary();
84                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT", "Accept");
85                         _srvVarsToHeaderMap.Add("HTTP_REFERER", "Referer");
86                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_LANGUAGE", "Accept-Language");
87                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_ENCODING", "Accept-Encoding");
88                         _srvVarsToHeaderMap.Add("HTTP_CONNECTION", "Connection");
89                         _srvVarsToHeaderMap.Add("HTTP_HOST", "Host");
90                         _srvVarsToHeaderMap.Add("HTTP_USER_AGENT", "User-Agent");
91                         _srvVarsToHeaderMap.Add("HTTP_SOAPACTION", "SOAPAction");
92
93                         string[] knownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
94                         KnownServerVariableMap = CollectionsUtil.CreateCaseInsensitiveHashtable(knownServerVariableNames.Length);
95                         for (int i = 0; i < knownServerVariableNames.Length; i++)
96                                 KnownServerVariableMap[knownServerVariableNames[i]] = (KnownServerVariable)i;
97                 }
98
99                 public ServletWorkerRequest (HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp, java.io.OutputStream outputStream) {
100                         _HttpServlet = servlet;
101                         _HttpServletRequest = req;
102                         _HttpServletResponse = resp;
103                         _OutputStream = outputStream;
104
105                         string contextPath = req.getContextPath();
106                         string requestURI = contextPath + req.getServletPath(); 
107
108                         _requestUri = Uri.UnescapeDataString(requestURI);
109                         const int dotInvokeLength = 7; //".invoke".Length
110                         if (_requestUri.Length > dotInvokeLength &&
111                                 String.CompareOrdinal(".invoke", 0, _requestUri, 
112                                 _requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
113
114                                 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
115                                 
116                                 int paramNameStart = _requestUri.LastIndexOf('/');
117                                 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
118                         }
119                 }
120
121                 public object GetService (Type serviceType)
122                 {
123                         if (serviceType == typeof(HttpServlet))
124                                 return Servlet;
125                         if (serviceType == typeof(HttpServletRequest))
126                                 return ServletRequest;
127                         if (serviceType == typeof(HttpServletResponse))
128                                 return ServletResponse;
129                         return null;
130                 }
131
132                 public HttpServlet Servlet {
133                         get {
134                                 return _HttpServlet;
135                         }
136                 }
137                 
138                 public HttpServletRequest ServletRequest {
139                         get{
140                                 return _HttpServletRequest;
141                         }
142                 }
143
144                 public HttpServletResponse ServletResponse {
145                         get{
146                                 return _HttpServletResponse;
147                         }
148                 }
149                 
150                 [MonoTODO("Implement security")]
151                 public override string MachineInstallDirectory {
152                         get {
153                                 return ".";
154                         }
155                 }
156
157                 public override string MachineConfigPath {
158                         get { return "."; }
159                 }
160
161                 public override void EndOfRequest () {
162                         if (_endOfSendCallback != null)
163                                 _endOfSendCallback(this, _endOfSendArgs);
164                         _OutputStream = null;
165                 }
166
167                 public override void FlushResponse (bool finalFlush) {
168                         IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
169                         if (_OutputStream == null || resp != null && resp.isRedirected())
170                                 return;
171
172                         _OutputStream.flush();
173                         if (finalFlush)
174                                 _OutputStream.close();
175                 }
176
177                 public override string GetAppPath () {
178                         return _HttpServletRequest.getContextPath();
179                 }
180                 public override string GetAppPathTranslated () {
181                         return J2EEUtils.GetApplicationRealPath(_HttpServlet.getServletConfig());;
182                 }
183
184                 public override string GetFilePath () {
185                         string uri = GetUriPath();
186                         string pathInfo = GetPathInfo();
187                         if (pathInfo != null && pathInfo.Length > 0)
188                                 uri = uri.Substring(0, uri.Length - pathInfo.Length);
189
190                         return uri;
191                 }
192
193                 public override string GetFilePathTranslated () {
194                         string page = GetFilePath ();
195
196                         if (Path.DirectorySeparatorChar != '/')
197                                 page = page.Replace ('/', Path.DirectorySeparatorChar);
198
199                         if (page [0] == Path.DirectorySeparatorChar)
200                                 page = page.Substring (1);
201                         
202                         return Path.Combine (GetAppPathTranslated (), page);
203                 }
204
205                 public override string GetHttpVerbName () {
206                         return _HttpServletRequest.getMethod();
207                 }
208
209                 public override string GetHttpVersion () {
210                         return _HttpServletRequest.getProtocol();
211                 }
212
213                 public override string GetLocalAddress () {
214                         return _HttpServletRequest.getLocalAddr();
215                 }
216
217                 public override int GetLocalPort () {
218                         return _HttpServletRequest.getServerPort();
219                 }
220
221                 public override string GetPathInfo () {
222                         string pathInfo = _pathInfo != null ? _pathInfo : _HttpServletRequest.getPathInfo();
223                         return pathInfo != null ? pathInfo : String.Empty;
224                 }
225
226                 public override string GetQueryString () {
227                         return _HttpServletRequest.getQueryString();
228                 }
229
230                 public override string GetRawUrl () {
231                         if (_rawUrl == null) {
232                                 StringBuilder builder = new StringBuilder();
233                                 builder.Append(GetUriPath());
234                                 string pathInfo = GetPathInfo();
235                                 string query = GetQueryString();
236                                 if (query != null && query.Length > 0) {
237                                         builder.Append('?');
238                                         builder.Append(query);
239                                 }
240
241                                 _rawUrl = builder.ToString();
242                         }
243
244                         return _rawUrl;
245                 }
246
247                 public override string GetRemoteAddress() {
248                         return _HttpServletRequest.getRemoteAddr();
249                 }
250
251                 public override string GetRemoteName() {
252                         return _HttpServletRequest.getRemoteHost();
253                 }
254
255
256                 public override int GetRemotePort() {
257                         try {
258                                 return _HttpServletRequest.getRemotePort();
259                         }
260                         catch(Exception e) {
261                                 // if servlet API is 2.3 and below - there is no method getRemotePort 
262                 // in ServletRequest interface... should be described as limitation.
263                                 return 0;
264                         }
265                 }
266
267                 public override string GetServerVariable(string name) {
268                         // FIXME: We need to make a proper mapping between the standard server
269                         // variables and java equivalent. probably we have to have a configuration file 
270                         // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
271                         // while implementing. Ensure that system web "common" code correctly calls each method.
272
273                         string headerName = _srvVarsToHeaderMap[name];
274
275                         if (headerName != null)
276                                 return _HttpServletRequest.getHeader( headerName );
277
278                         object knownVariable = KnownServerVariableMap[name];
279                         if (knownVariable != null)
280                                 return GetKnownServerVariable((KnownServerVariable)knownVariable);
281
282                         return _HttpServletRequest.getHeader( name );
283                 }
284
285                 string GetKnownServerVariable(KnownServerVariable index) {
286                         switch (index) {
287                                 case KnownServerVariable.AUTH_TYPE : return _HttpServletRequest.getAuthType();
288                                 case KnownServerVariable.CONTENT_LENGTH : return Convert.ToString(_HttpServletRequest.getContentLength());
289                                 case KnownServerVariable.CONTENT_TYPE : return _HttpServletRequest.getContentType();
290                                 case KnownServerVariable.QUERY_STRING : return GetQueryString();
291                                 case KnownServerVariable.REMOTE_ADDR : return GetRemoteAddress();
292                                 case KnownServerVariable.REMOTE_HOST : return GetRemoteName();
293                                 case KnownServerVariable.REMOTE_USER : return _HttpServletRequest.getRemoteUser();
294                                 case KnownServerVariable.REQUEST_METHOD : return GetHttpVerbName ();
295                                 case KnownServerVariable.REQUEST_URI : return GetUriPath();
296                                 case KnownServerVariable.SCRIPT_NAME : return GetFilePath ();
297                                 case KnownServerVariable.SERVER_NAME : return GetServerName();
298                                 case KnownServerVariable.SERVER_PORT : return Convert.ToString(_HttpServletRequest.getServerPort());
299                                 case KnownServerVariable.SERVER_PROTOCOL : return GetHttpVersion ();
300                                 case KnownServerVariable.SERVER_SOFTWARE : return Servlet.getServletContext().getServerInfo();
301                                 case KnownServerVariable.PATH_INFO : return GetPathInfo();
302                                 default: throw new IndexOutOfRangeException("index");
303                         }
304                 }
305
306                 public override string GetUriPath() {
307                         return _requestUri;
308                 }
309
310                 public override IntPtr GetUserToken() {
311                         return IntPtr.Zero;
312                 }
313
314                 public override string MapPath (string virtualPath) {
315                         if (virtualPath == null)
316                                 throw new ArgumentNullException ("virtualPath");
317                         int appVirtualPathIndex = virtualPath.IndexOf ('/', 1);
318                         string appVirtualPath;
319                         if (appVirtualPathIndex < 0) {
320                                 appVirtualPathIndex = virtualPath.Length;
321                                 appVirtualPath = String.Empty;
322                         }
323                         else
324                                 appVirtualPath = virtualPath.Substring(appVirtualPathIndex);
325
326                         ServletConfig config = _HttpServlet.getServletConfig ();                        
327
328                         string contextPath = GetAppPath ();
329                         if (contextPath.Length != appVirtualPathIndex ||
330                                 string.CompareOrdinal (contextPath, 0, virtualPath, 0, appVirtualPathIndex) != 0) {
331
332                                 ServletContext context = config.getServletContext ().getContext (virtualPath.Remove (appVirtualPathIndex));
333                                 string retVal;
334                                 if (context == null || ((retVal = context.getRealPath (appVirtualPath)) == null))
335                                         throw new HttpException ("MapPath: Mapping across applications not allowed");
336
337                                 return retVal;
338                         }
339                         else
340                                 return J2EEUtils.GetApplicationRealPath (config, appVirtualPath);
341                 }
342
343                 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
344                         throw new NotSupportedException();
345                 }
346
347                 public override void SendResponseFromFile (string filename, long offset, long length) {
348                         using (FileStream fs = File.OpenRead (filename)) {
349                                 byte [] buffer = new byte [4 * 1024];
350
351                                 if (offset != 0)
352                                         fs.Position = offset;
353
354                                 long remain = length;
355                                 int n;
356                                 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
357                                         remain -= n;
358                                         SendResponseFromMemory(buffer, n);
359                                 }
360                         }
361                 }
362
363                 public override void SendResponseFromMemory (byte [] data, int length) {
364                         IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
365                         if (_OutputStream == null || resp != null && resp.isRedirected())
366                                 return;
367
368                         sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
369                         _OutputStream.write(sdata, 0 , length);
370                 }
371
372                 public override void SendStatus(int statusCode, string statusDescription) {
373                         // setStatus(int, string) is deprecated
374                         _HttpServletResponse.setStatus(statusCode/*, statusDescription*/);
375                 }
376
377                 public override void SendUnknownResponseHeader(string name, string value) {
378                         if (HeadersSent ())
379                                 return;
380
381                         _HttpServletResponse.addHeader(name, value);
382                 }
383
384                 public override bool HeadersSent () {
385                         return _HttpServletResponse.isCommitted();
386                 }
387
388                 public override void SendCalculatedContentLength (int contentLength) {
389                         _HttpServletResponse.setContentLength(contentLength);
390                 }
391
392                 public override void SendKnownResponseHeader (int index, string value) {
393                         SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
394                 }
395
396                 public override string GetKnownRequestHeader (int index) {      
397                         return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
398                 }
399
400                 public override string GetUnknownRequestHeader (string name) {
401                         return _HttpServletRequest.getHeader(name);
402                 }
403
404                 public override string [][] GetUnknownRequestHeaders () {
405                         if (unknownHeaders == null) {
406                                 ArrayList pairs = new ArrayList ();
407                                 for (java.util.Enumeration he = _HttpServletRequest.getHeaderNames(); he.hasMoreElements() ;) {
408                                         string key = (string) he.nextElement();
409                                         int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
410                                         if (index != -1)
411                                                 continue;
412                                         pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
413                                 }
414                                 
415                                 if (pairs.Count != 0) {
416                                         unknownHeaders = new string [pairs.Count][];
417                                         for (int i = 0; i < pairs.Count; i++)
418                                                 unknownHeaders [i] = (string []) pairs [i];
419                                 }
420                         }
421                         if (unknownHeaders == null) unknownHeaders = new string [0][];
422
423                         return unknownHeaders;
424                 }
425
426                 public override int ReadEntityBody (byte [] buffer, int size) {
427                         if (buffer == null || size == 0)
428                                 return 0;
429                         sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
430                         InputStream inp = _HttpServletRequest.getInputStream();
431                         if (inp == null && _HttpServletRequest is IPortletActionRequest)
432                                 inp = ((IPortletActionRequest) _HttpServletRequest).getPortletInputStream();
433                         int r = (inp != null) ? inp.read(sbuffer, 0, size) : -1;
434                         return r == -1 ? 0 : r;
435                 }
436
437                 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
438                         _endOfSendCallback = callback;
439                         _endOfSendArgs = extraData;
440                 }
441
442                 public override string GetProtocol() {
443                         return _HttpServletRequest.getScheme();
444                 }
445
446                 public override string GetServerName() {
447                         return _HttpServletRequest.getServerName();
448                 }
449
450                 public override bool IsSecure() {
451                         return _HttpServletRequest.isSecure();
452                 }
453         }
454 }
455