Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » coyote » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.coyote;
   19   
   20   import java.io.IOException;
   21   import java.util.HashMap;
   22   
   23   import org.apache.tomcat.util.buf.ByteChunk;
   24   import org.apache.tomcat.util.buf.MessageBytes;
   25   import org.apache.tomcat.util.buf.UDecoder;
   26   
   27   import org.apache.tomcat.util.http.MimeHeaders;
   28   import org.apache.tomcat.util.http.Parameters;
   29   import org.apache.tomcat.util.http.ContentType;
   30   import org.apache.tomcat.util.http.Cookies;
   31   
   32   /**
   33    * This is a low-level, efficient representation of a server request. Most 
   34    * fields are GC-free, expensive operations are delayed until the  user code 
   35    * needs the information.
   36    *
   37    * Processing is delegated to modules, using a hook mechanism.
   38    * 
   39    * This class is not intended for user code - it is used internally by tomcat
   40    * for processing the request in the most efficient way. Users ( servlets ) can
   41    * access the information using a facade, which provides the high-level view
   42    * of the request.
   43    *
   44    * For lazy evaluation, the request uses the getInfo() hook. The following ids
   45    * are defined:
   46    * <ul>
   47    *  <li>req.encoding - returns the request encoding
   48    *  <li>req.attribute - returns a module-specific attribute ( like SSL keys, etc ).
   49    * </ul>
   50    *
   51    * Tomcat defines a number of attributes:
   52    * <ul>
   53    *   <li>"org.apache.tomcat.request" - allows access to the low-level
   54    *       request object in trusted applications 
   55    * </ul>
   56    *
   57    * @author James Duncan Davidson [duncan@eng.sun.com]
   58    * @author James Todd [gonzo@eng.sun.com]
   59    * @author Jason Hunter [jch@eng.sun.com]
   60    * @author Harish Prabandham
   61    * @author Alex Cruikshank [alex@epitonic.com]
   62    * @author Hans Bergsten [hans@gefionsoftware.com]
   63    * @author Costin Manolache
   64    * @author Remy Maucherat
   65    */
   66   public final class Request {
   67   
   68   
   69       // ----------------------------------------------------------- Constructors
   70   
   71   
   72       public Request() {
   73   
   74           parameters.setQuery(queryMB);
   75           parameters.setURLDecoder(urlDecoder);
   76           parameters.setHeaders(headers);
   77   
   78       }
   79   
   80   
   81       // ----------------------------------------------------- Instance Variables
   82   
   83   
   84       private int serverPort = -1;
   85       private MessageBytes serverNameMB = MessageBytes.newInstance();
   86   
   87       private int remotePort;
   88       private int localPort;
   89   
   90       private MessageBytes schemeMB = MessageBytes.newInstance();
   91   
   92       private MessageBytes methodMB = MessageBytes.newInstance();
   93       private MessageBytes unparsedURIMB = MessageBytes.newInstance();
   94       private MessageBytes uriMB = MessageBytes.newInstance();
   95       private MessageBytes decodedUriMB = MessageBytes.newInstance();
   96       private MessageBytes queryMB = MessageBytes.newInstance();
   97       private MessageBytes protoMB = MessageBytes.newInstance();
   98   
   99       // remote address/host
  100       private MessageBytes remoteAddrMB = MessageBytes.newInstance();
  101       private MessageBytes localNameMB = MessageBytes.newInstance();
  102       private MessageBytes remoteHostMB = MessageBytes.newInstance();
  103       private MessageBytes localAddrMB = MessageBytes.newInstance();
  104        
  105       private MimeHeaders headers = new MimeHeaders();
  106   
  107       private MessageBytes instanceId = MessageBytes.newInstance();
  108   
  109       /**
  110        * Notes.
  111        */
  112       private Object notes[] = new Object[Constants.MAX_NOTES];
  113   
  114   
  115       /**
  116        * Associated input buffer.
  117        */
  118       private InputBuffer inputBuffer = null;
  119   
  120   
  121       /**
  122        * URL decoder.
  123        */
  124       private UDecoder urlDecoder = new UDecoder();
  125   
  126   
  127       /**
  128        * HTTP specific fields. (remove them ?)
  129        */
  130       private long contentLength = -1;
  131       private MessageBytes contentTypeMB = null;
  132       private String charEncoding = null;
  133       private Cookies cookies = new Cookies(headers);
  134       private Parameters parameters = new Parameters();
  135   
  136       private MessageBytes remoteUser=MessageBytes.newInstance();
  137       private MessageBytes authType=MessageBytes.newInstance();
  138       private HashMap attributes=new HashMap();
  139   
  140       private Response response;
  141       private ActionHook hook;
  142   
  143       private int bytesRead=0;
  144       // Time of the request - usefull to avoid repeated calls to System.currentTime
  145       private long startTime = 0L;
  146       private int available = 0;
  147   
  148       private RequestInfo reqProcessorMX=new RequestInfo(this);
  149       // ------------------------------------------------------------- Properties
  150   
  151   
  152       /**
  153        * Get the instance id (or JVM route). Curently Ajp is sending it with each
  154        * request. In future this should be fixed, and sent only once ( or
  155        * 'negociated' at config time so both tomcat and apache share the same name.
  156        * 
  157        * @return the instance id
  158        */
  159       public MessageBytes instanceId() {
  160           return instanceId;
  161       }
  162   
  163   
  164       public MimeHeaders getMimeHeaders() {
  165           return headers;
  166       }
  167   
  168   
  169       public UDecoder getURLDecoder() {
  170           return urlDecoder;
  171       }
  172   
  173       // -------------------- Request data --------------------
  174   
  175   
  176       public MessageBytes scheme() {
  177           return schemeMB;
  178       }
  179       
  180       public MessageBytes method() {
  181           return methodMB;
  182       }
  183       
  184       public MessageBytes unparsedURI() {
  185           return unparsedURIMB;
  186       }
  187   
  188       public MessageBytes requestURI() {
  189           return uriMB;
  190       }
  191   
  192       public MessageBytes decodedURI() {
  193           return decodedUriMB;
  194       }
  195   
  196       public MessageBytes query() {
  197           return queryMB;
  198       }
  199   
  200       public MessageBytes queryString() {
  201           return queryMB;
  202       }
  203   
  204       public MessageBytes protocol() {
  205           return protoMB;
  206       }
  207       
  208       /** 
  209        * Return the buffer holding the server name, if
  210        * any. Use isNull() to check if there is no value
  211        * set.
  212        * This is the "virtual host", derived from the
  213        * Host: header.
  214        */
  215       public MessageBytes serverName() {
  216           return serverNameMB;
  217       }
  218   
  219       public int getServerPort() {
  220           return serverPort;
  221       }
  222       
  223       public void setServerPort(int serverPort ) {
  224           this.serverPort=serverPort;
  225       }
  226   
  227       public MessageBytes remoteAddr() {
  228           return remoteAddrMB;
  229       }
  230   
  231       public MessageBytes remoteHost() {
  232           return remoteHostMB;
  233       }
  234   
  235       public MessageBytes localName() {
  236           return localNameMB;
  237       }    
  238   
  239       public MessageBytes localAddr() {
  240           return localAddrMB;
  241       }
  242       
  243       public int getRemotePort(){
  244           return remotePort;
  245       }
  246           
  247       public void setRemotePort(int port){
  248           this.remotePort = port;
  249       }
  250       
  251       public int getLocalPort(){
  252           return localPort;
  253       }
  254           
  255       public void setLocalPort(int port){
  256           this.localPort = port;
  257       }
  258   
  259       // -------------------- encoding/type --------------------
  260   
  261   
  262       /**
  263        * Get the character encoding used for this request.
  264        */
  265       public String getCharacterEncoding() {
  266   
  267           if (charEncoding != null)
  268               return charEncoding;
  269   
  270           charEncoding = ContentType.getCharsetFromContentType(getContentType());
  271           return charEncoding;
  272   
  273       }
  274   
  275   
  276       public void setCharacterEncoding(String enc) {
  277           this.charEncoding = enc;
  278       }
  279   
  280   
  281       public void setContentLength(int len) {
  282           this.contentLength = len;
  283       }
  284   
  285   
  286       public int getContentLength() {
  287           long length = getContentLengthLong();
  288   
  289           if (length < Integer.MAX_VALUE) {
  290               return (int) length;
  291           }
  292           return -1;
  293       }
  294   
  295       public long getContentLengthLong() {
  296           if( contentLength > -1 ) return contentLength;
  297   
  298           MessageBytes clB = headers.getUniqueValue("content-length");
  299           contentLength = (clB == null || clB.isNull()) ? -1 : clB.getLong();
  300   
  301           return contentLength;
  302       }
  303   
  304       public String getContentType() {
  305           contentType();
  306           if ((contentTypeMB == null) || contentTypeMB.isNull()) 
  307               return null;
  308           return contentTypeMB.toString();
  309       }
  310   
  311   
  312       public void setContentType(String type) {
  313           contentTypeMB.setString(type);
  314       }
  315   
  316   
  317       public MessageBytes contentType() {
  318           if (contentTypeMB == null)
  319               contentTypeMB = headers.getValue("content-type");
  320           return contentTypeMB;
  321       }
  322   
  323   
  324       public void setContentType(MessageBytes mb) {
  325           contentTypeMB=mb;
  326       }
  327   
  328   
  329       public String getHeader(String name) {
  330           return headers.getHeader(name);
  331       }
  332   
  333       // -------------------- Associated response --------------------
  334   
  335       public Response getResponse() {
  336           return response;
  337       }
  338   
  339       public void setResponse( Response response ) {
  340           this.response=response;
  341           response.setRequest( this );
  342       }
  343       
  344       public void action(ActionCode actionCode, Object param) {
  345           if( hook==null && response!=null )
  346               hook=response.getHook();
  347           
  348           if (hook != null) {
  349               if( param==null ) 
  350                   hook.action(actionCode, this);
  351               else
  352                   hook.action(actionCode, param);
  353           }
  354       }
  355   
  356   
  357       // -------------------- Cookies --------------------
  358   
  359   
  360       public Cookies getCookies() {
  361           return cookies;
  362       }
  363   
  364   
  365       // -------------------- Parameters --------------------
  366   
  367   
  368       public Parameters getParameters() {
  369           return parameters;
  370       }
  371   
  372   
  373       // -------------------- Other attributes --------------------
  374       // We can use notes for most - need to discuss what is of general interest
  375       
  376       public void setAttribute( String name, Object o ) {
  377           attributes.put( name, o );
  378       }
  379   
  380       public HashMap getAttributes() {
  381           return attributes;
  382       }
  383   
  384       public Object getAttribute(String name ) {
  385           return attributes.get(name);
  386       }
  387       
  388       public MessageBytes getRemoteUser() {
  389           return remoteUser;
  390       }
  391   
  392       public MessageBytes getAuthType() {
  393           return authType;
  394       }
  395   
  396       public int getAvailable() {
  397           return available;
  398       }
  399   
  400       public void setAvailable(int available) {
  401           this.available = available;
  402       }
  403   
  404       // -------------------- Input Buffer --------------------
  405   
  406   
  407       public InputBuffer getInputBuffer() {
  408           return inputBuffer;
  409       }
  410   
  411   
  412       public void setInputBuffer(InputBuffer inputBuffer) {
  413           this.inputBuffer = inputBuffer;
  414       }
  415   
  416   
  417       /**
  418        * Read data from the input buffer and put it into a byte chunk.
  419        *
  420        * The buffer is owned by the protocol implementation - it will be reused on the next read.
  421        * The Adapter must either process the data in place or copy it to a separate buffer if it needs
  422        * to hold it. In most cases this is done during byte->char conversions or via InputStream. Unlike
  423        * InputStream, this interface allows the app to process data in place, without copy.
  424        *
  425        */
  426       public int doRead(ByteChunk chunk) 
  427           throws IOException {
  428           int n = inputBuffer.doRead(chunk, this);
  429           if (n > 0) {
  430               bytesRead+=n;
  431           }
  432           return n;
  433       }
  434   
  435   
  436       // -------------------- debug --------------------
  437   
  438       public String toString() {
  439           return "R( " + requestURI().toString() + ")";
  440       }
  441   
  442       public long getStartTime() {
  443           return startTime;
  444       }
  445   
  446       public void setStartTime(long startTime) {
  447           this.startTime = startTime;
  448       }
  449   
  450       // -------------------- Per-Request "notes" --------------------
  451   
  452   
  453       /** 
  454        * Used to store private data. Thread data could be used instead - but 
  455        * if you have the req, getting/setting a note is just a array access, may
  456        * be faster than ThreadLocal for very frequent operations.
  457        * 
  458        *  Example use: 
  459        *   Jk:
  460        *     HandlerRequest.HOSTBUFFER = 10 CharChunk, buffer for Host decoding
  461        *     WorkerEnv: SSL_CERT_NOTE=16 - MessageBytes containing the cert
  462        *                
  463        *   Catalina CoyoteAdapter:
  464        *      ADAPTER_NOTES = 1 - stores the HttpServletRequest object ( req/res)             
  465        *      
  466        *   To avoid conflicts, note in the range 0 - 8 are reserved for the 
  467        *   servlet container ( catalina connector, etc ), and values in 9 - 16 
  468        *   for connector use. 
  469        *   
  470        *   17-31 range is not allocated or used.
  471        */
  472       public final void setNote(int pos, Object value) {
  473           notes[pos] = value;
  474       }
  475   
  476   
  477       public final Object getNote(int pos) {
  478           return notes[pos];
  479       }
  480   
  481   
  482       // -------------------- Recycling -------------------- 
  483   
  484   
  485       public void recycle() {
  486           bytesRead=0;
  487   
  488           contentLength = -1;
  489           contentTypeMB = null;
  490           charEncoding = null;
  491           headers.recycle();
  492           serverNameMB.recycle();
  493           serverPort=-1;
  494           localPort = -1;
  495           remotePort = -1;
  496           available = 0;
  497   
  498           cookies.recycle();
  499           parameters.recycle();
  500   
  501           unparsedURIMB.recycle();
  502           uriMB.recycle(); 
  503           decodedUriMB.recycle();
  504           queryMB.recycle();
  505           methodMB.recycle();
  506           protoMB.recycle();
  507   
  508           schemeMB.recycle();
  509   
  510           instanceId.recycle();
  511           remoteUser.recycle();
  512           authType.recycle();
  513           attributes.clear();
  514       }
  515   
  516       // -------------------- Info  --------------------
  517       public void updateCounters() {
  518           reqProcessorMX.updateCounters();
  519       }
  520   
  521       public RequestInfo getRequestProcessor() {
  522           return reqProcessorMX;
  523       }
  524   
  525       public int getBytesRead() {
  526           return bytesRead;
  527       }
  528   
  529       public void setBytesRead(int bytesRead) {
  530           this.bytesRead = bytesRead;
  531       }
  532   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » coyote » [javadoc | source]