public static HttpRequest readRequest(Stream inputStream)
        {
            MutableData buffer = new MutableData();

            String firstLine = readLine(inputStream, buffer);
            log.debug(firstLine, "firstLine");

            // null corresponds to the end of a stream
            if (null == firstLine)
            {
                return null;
            }

            HttpRequest answer = new HttpRequest();
            setOperationDetailsForRequest(answer, firstLine);

            int i = 0;
            do 
            {
                buffer.clear();
                String line = readLine(inputStream, buffer);
                if (0 == line.Length)
                {
                    break;
                }
                else
                {
                    addHeader(line, answer);
                }

            } while (i < NUMBER_HEADERS_UPPER_BOUND);

            if (i > NUMBER_HEADERS_UPPER_BOUND)
            {
                log.errorFormat("i > NUMBER_HEADERS_UPPER_BOUND; i = {0}", i);
                throw HttpErrorHelper.badRequest400FromOriginator(typeof(HttpRequestReader));
            }

            String contentLengthString = null;

            if (answer.headers.ContainsKey("content-length"))
            {
                contentLengthString = answer.headers["content-length"];
            }

            // no body ?
            if (null == contentLengthString)
            {
                log.debug("null == contentLengthString");
                return answer;
            }


            long contentLength = Int64.Parse(contentLengthString);
            log.debug(contentLength, "contentLength");

            Entity body = new StreamEntity(contentLength, inputStream);
            answer.Entity = body;

            return answer;

        }
        public Entity readFile(FileInfo fileInfo)
        {

            // Make sure they aren't trying in funny business by checking that the
            // resulting canonical name of the file has the doc root as a subset.
            var filePath = fileInfo.FullName;
            if (!filePath.StartsWith(_docRootFile.FullName))
            {
				log.errorFormat("!filePath.StartsWith(_docRootFile.FullName); filePath = {0}; _docRootFile.FullName = {1}", filePath, _docRootFile.FullName);
                throw HttpErrorHelper.forbidden403FromOriginator(this);

            }

            if (!fileInfo.Exists)
            {
                log.errorFormat("!fileInfo.Exists; file.FullName = {0}", fileInfo.FullName);
                throw HttpErrorHelper.notFound404FromOriginator(this);
            }


            // can read ? 
            { 

                FileIOPermission readPermission = new FileIOPermission(FileIOPermissionAccess.Read, fileInfo.FullName);
                if (!SecurityManager.IsGranted(readPermission))
                {
                    log.errorFormat("!SecurityManager.IsGranted(readPermission); fileInfo.FullName = {0}", fileInfo.FullName);
                    throw HttpErrorHelper.forbidden403FromOriginator(this);
                }
            }

            
            try
            {
                FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
                StreamEntity answer = new StreamEntity(fileInfo.Length, fs);
                return answer;
            }
            catch (Exception e)
            {
                log.errorFormat("exception caught trying open file; fileInfo.FullName = {0}; e.Message = {1}", fileInfo.FullName, e.Message);
                throw HttpErrorHelper.notFound404FromOriginator(this);
            }

        }