/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:  
 *       "This product includes software developed by the 
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Pluto", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * ====================================================================
 *
 * This source code implements specifications defined by the Java
 * Community Process. In order to remain compliant with the specification
 * DO NOT add / change / or delete method signatures!
 */

package javax.portlet;


/**
 * The <CODE>ActionRequest</CODE> represents the request sent to the portlet
 * to handle an action.
 * It extends the PortletRequest interface to provide action request
 * information to portlets.<br>
 * The portlet container creates an <CODE>ActionRequest</CODE> object and
 * passes it as argument to the portlet's <CODE>processAction</CODE> method.
 * 
 * @see PortletRequest
 * @see RenderRequest
 */
public interface ActionRequest extends PortletRequest
{



  /**
   * Retrieves the body of the HTTP request from client to
   * portal as binary data using
   * an <CODE>InputStream</CODE>. Either this method or 
   * {@link #getReader} may be called to read the body, but not both.
   * <p>
   * For HTTP POST data of type application/x-www-form-urlencoded
   * this method throws an <code>IllegalStateException</code>
   * as this data has been already processed by the 
   * portal/portlet-container and is available as request parameters.
   *
   * @return an input stream containing the body of the request
   *
   * @exception java.lang.IllegalStateException
   *                   if getReader was already called, or it is a 
   *                   HTTP POST data of type application/x-www-form-urlencoded
   * @exception java.io.IOException
   *                   if an input or output exception occurred
   */
  public java.io.InputStream getPortletInputStream () throws java.io.IOException;



  /**
   * Overrides the name of the character encoding used in the body of this
   * request. This method must be called prior to reading input 
   * using {@link #getReader} or {@link #getPortletInputStream}.
   * <p>
   * This method only sets the character set for the Reader that the
   * {@link #getReader} method returns.
   *
   * @param	enc	a <code>String</code> containing the name of 
   *			the chararacter encoding.
   *
   * @exception		java.io.UnsupportedEncodingException if this is not a valid encoding
   * @exception		java.lang.IllegalStateException      if this method is called after 
   *                                   reading request parameters or reading input using 
   *                                   <code>getReader()</code>
   */

  public void setCharacterEncoding(String enc) 
    throws java.io.UnsupportedEncodingException;


  /**
   * Retrieves the body of the HTTP request from the client to the portal
   * as character data using
   * a <code>BufferedReader</code>.  The reader translates the character
   * data according to the character encoding used on the body.
   * Either this method or {@link #getPortletInputStream} may be called to read the
   * body, not both.
   * <p>
   * For HTTP POST data of type application/x-www-form-urlencoded
   * this method throws an <code>IllegalStateException</code>
   * as this data has been already processed by the 
   * portal/portlet-container and is available as request parameters.
   *
   * @return	a <code>BufferedReader</code>
   *		containing the body of the request	
   *
   * @exception  java.io.UnsupportedEncodingException 	
   *                 if the character set encoding used is 
   * 		     not supported and the text cannot be decoded
   * @exception  java.lang.IllegalStateException   	
   *                 if {@link #getPortletInputStream} method
   * 		     has been called on this request,  it is a 
   *                   HTTP POST data of type application/x-www-form-urlencoded.
   * @exception  java.io.IOException
   *                 if an input or output exception occurred
   *
   * @see #getPortletInputStream
   */
  
  public java.io.BufferedReader getReader()
    throws java.io.UnsupportedEncodingException, java.io.IOException;
    
    
  /**
   * Returns the name of the character encoding used in the body of this request.
   * This method returns <code>null</code> if the request
   * does not specify a character encoding.
   *
   * @return		a <code>String</code> containing the name of 
   *			the chararacter encoding, or <code>null</code>
   *			if the request does not specify a character encoding.
   */
  
  public java.lang.String getCharacterEncoding();



  /**
   * Returns the MIME type of the body of the request, 
   * or null if the type is not known.
   *
   * @return		a <code>String</code> containing the name 
   *			of the MIME type of the request, or null 
   *                    if the type is not known.
   */

  public java.lang.String getContentType();


  /**
   * Returns the length, in bytes, of the request body 
   * which is made available by the input stream, or -1 if the
   * length is not known. 
   *
   *
   * @return		an integer containing the length of the 
   * 			request body or -1 if the length is not known
   *
   */

  public int getContentLength();
    

    

}
