2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
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:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
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.
28 using System.Runtime.InteropServices;
29 using System.Web.Util;
30 using System.Web.J2EE;
31 using System.Collections;
34 using javax.servlet.http;
35 using System.Collections.Specialized;
36 using System.Globalization;
37 using System.Web.Hosting;
39 using vmw.@internal.j2ee;
40 using InputStream=java.io.InputStream;
42 namespace Mainsoft.Web.Hosting {
43 [MonoTODO("Implement security demands on the path usage functions (and review)")]
45 internal sealed class ServletWorkerRequest : HttpWorkerRequest, IServiceProvider {
46 readonly HttpServlet _HttpServlet;
47 readonly HttpServletRequest _HttpServletRequest;
48 readonly HttpServletResponse _HttpServletResponse;
49 java.io.OutputStream _OutputStream;
51 readonly string _requestUri;
52 readonly string _pathInfo;
54 static readonly StringDictionary _srvVarsToHeaderMap;
56 private string [][] unknownHeaders;
59 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
60 private object _endOfSendArgs;
62 enum KnownServerVariable {
80 static readonly Hashtable KnownServerVariableMap;
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");
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;
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;
105 string contextPath = req.getContextPath();
106 string requestURI = contextPath + req.getServletPath();
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) {
114 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
116 int paramNameStart = _requestUri.LastIndexOf('/');
117 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
121 public object GetService (Type serviceType)
123 if (serviceType == typeof(HttpServlet))
125 if (serviceType == typeof(HttpServletRequest))
126 return ServletRequest;
127 if (serviceType == typeof(HttpServletResponse))
128 return ServletResponse;
132 public HttpServlet Servlet {
138 public HttpServletRequest ServletRequest {
140 return _HttpServletRequest;
144 public HttpServletResponse ServletResponse {
146 return _HttpServletResponse;
150 [MonoTODO("Implement security")]
151 public override string MachineInstallDirectory {
157 public override string MachineConfigPath {
161 public override void EndOfRequest () {
162 if (_endOfSendCallback != null)
163 _endOfSendCallback(this, _endOfSendArgs);
164 _OutputStream = null;
167 public override void FlushResponse (bool finalFlush) {
168 IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
169 if (_OutputStream == null || resp != null && resp.isRedirected())
172 _OutputStream.flush();
174 _OutputStream.close();
177 public override string GetAppPath () {
178 return _HttpServletRequest.getContextPath();
180 public override string GetAppPathTranslated () {
181 return J2EEUtils.GetApplicationRealPath(_HttpServlet.getServletConfig());;
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);
193 public override string GetFilePathTranslated () {
194 string page = GetFilePath ();
196 if (Path.DirectorySeparatorChar != '/')
197 page = page.Replace ('/', Path.DirectorySeparatorChar);
199 if (page [0] == Path.DirectorySeparatorChar)
200 page = page.Substring (1);
202 return Path.Combine (GetAppPathTranslated (), page);
205 public override string GetHttpVerbName () {
206 return _HttpServletRequest.getMethod();
209 public override string GetHttpVersion () {
210 return _HttpServletRequest.getProtocol();
213 public override string GetLocalAddress () {
214 return _HttpServletRequest.getLocalAddr();
217 public override int GetLocalPort () {
218 return _HttpServletRequest.getServerPort();
221 public override string GetPathInfo () {
222 string pathInfo = _pathInfo != null ? _pathInfo : _HttpServletRequest.getPathInfo();
223 return pathInfo != null ? pathInfo : String.Empty;
226 public override string GetQueryString () {
227 return _HttpServletRequest.getQueryString();
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) {
238 builder.Append(query);
241 _rawUrl = builder.ToString();
247 public override string GetRemoteAddress() {
248 return _HttpServletRequest.getRemoteAddr();
251 public override string GetRemoteName() {
252 return _HttpServletRequest.getRemoteHost();
256 public override int GetRemotePort() {
258 return _HttpServletRequest.getRemotePort();
261 // if servlet API is 2.3 and below - there is no method getRemotePort
262 // in ServletRequest interface... should be described as limitation.
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.
273 string headerName = _srvVarsToHeaderMap[name];
275 if (headerName != null)
276 return _HttpServletRequest.getHeader( headerName );
278 object knownVariable = KnownServerVariableMap[name];
279 if (knownVariable != null)
280 return GetKnownServerVariable((KnownServerVariable)knownVariable);
282 return _HttpServletRequest.getHeader( name );
285 string GetKnownServerVariable(KnownServerVariable 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");
306 public override string GetUriPath() {
310 public override IntPtr GetUserToken() {
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;
324 appVirtualPath = virtualPath.Substring(appVirtualPathIndex);
326 ServletConfig config = _HttpServlet.getServletConfig ();
328 string contextPath = GetAppPath ();
329 if (contextPath.Length != appVirtualPathIndex ||
330 string.CompareOrdinal (contextPath, 0, virtualPath, 0, appVirtualPathIndex) != 0) {
332 ServletContext context = config.getServletContext ().getContext (virtualPath.Remove (appVirtualPathIndex));
334 if (context == null || ((retVal = context.getRealPath (appVirtualPath)) == null))
335 throw new HttpException ("MapPath: Mapping across applications not allowed");
340 return J2EEUtils.GetApplicationRealPath (config, appVirtualPath);
343 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
344 throw new NotSupportedException();
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];
352 fs.Position = offset;
354 long remain = length;
356 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
358 SendResponseFromMemory(buffer, n);
363 public override void SendResponseFromMemory (byte [] data, int length) {
364 IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
365 if (_OutputStream == null || resp != null && resp.isRedirected())
368 sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
369 _OutputStream.write(sdata, 0 , length);
372 public override void SendStatus(int statusCode, string statusDescription) {
373 // setStatus(int, string) is deprecated
374 _HttpServletResponse.setStatus(statusCode/*, statusDescription*/);
377 public override void SendUnknownResponseHeader(string name, string value) {
381 _HttpServletResponse.addHeader(name, value);
384 public override bool HeadersSent () {
385 return _HttpServletResponse.isCommitted();
388 public override void SendCalculatedContentLength (int contentLength) {
389 _HttpServletResponse.setContentLength(contentLength);
392 public override void SendKnownResponseHeader (int index, string value) {
393 SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
396 public override string GetKnownRequestHeader (int index) {
397 return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
400 public override string GetUnknownRequestHeader (string name) {
401 return _HttpServletRequest.getHeader(name);
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);
412 pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
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];
421 if (unknownHeaders == null) unknownHeaders = new string [0][];
423 return unknownHeaders;
426 public override int ReadEntityBody (byte [] buffer, int size) {
427 if (buffer == null || size == 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;
437 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
438 _endOfSendCallback = callback;
439 _endOfSendArgs = extraData;
442 public override string GetProtocol() {
443 return _HttpServletRequest.getScheme();
446 public override string GetServerName() {
447 return _HttpServletRequest.getServerName();
450 public override bool IsSecure() {
451 return _HttpServletRequest.isSecure();