View Javadoc

    1   package org.apache.turbine.services.rundata;
    2
    3   /*
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *   http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21
    22  import java.io.IOException;
    23  import java.io.PrintWriter;
    24  import java.util.ArrayList;
    25  import java.util.HashMap;
    26  import java.util.List;
    27  import java.util.Locale;
    28  import java.util.Map;
    29
    30  import javax.naming.Context;
    31  import javax.servlet.ServletConfig;
    32  import javax.servlet.ServletContext;
    33  import javax.servlet.http.HttpServletRequest;
    34  import javax.servlet.http.HttpServletResponse;
    35  import javax.servlet.http.HttpSession;
    36
    37  import org.apache.commons.lang.StringUtils;
    38  import org.apache.commons.logging.Log;
    39  import org.apache.commons.logging.LogFactory;
    40  import org.apache.ecs.Document;
    41  import org.apache.ecs.Element;
    42  import org.apache.ecs.StringElement;
    43  import org.apache.fulcrum.mimetype.MimeTypeService;
    44  import org.apache.fulcrum.parser.CookieParser;
    45  import org.apache.fulcrum.parser.ParameterParser;
    46  import org.apache.fulcrum.pool.Recyclable;
    47  import org.apache.turbine.Turbine;
    48  import org.apache.turbine.TurbineConstants;
    49  import org.apache.turbine.om.security.User;
    50  import org.apache.turbine.pipeline.DefaultPipelineData;
    51  import org.apache.turbine.services.ServiceManager;
    52  import org.apache.turbine.services.TurbineServices;
    53  import org.apache.turbine.services.template.TurbineTemplate;
    54  import org.apache.turbine.util.FormMessages;
    55  import org.apache.turbine.util.ServerData;
    56  import org.apache.turbine.util.SystemError;
    57  import org.apache.turbine.util.security.AccessControlList;
    58  import org.apache.turbine.util.template.TemplateInfo;
    59
    60  /**
    61   * DefaultTurbineRunData is the default implementation of the
    62   * TurbineRunData interface, which is distributed by the Turbine
    63   * RunData service, if another implementation is not defined in
    64   * the default or specified RunData configuration.
    65   * TurbineRunData is an extension to RunData, which
    66   * is an interface to run-rime information that is passed
    67   * within Turbine. This provides the threading mechanism for the
    68   * entire system because multiple requests can potentially come in
    69   * at the same time.  Thus, there is only one RunData implementation
    70   * for each request that is being serviced.
    71   *
    72   * <p>DefaultTurbineRunData implements the Recyclable interface making
    73   * it possible to pool its instances for recycling.
    74   *
    75   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
    76   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
    77   * @author <a href="mailto:bhoeneis@ee.ethz.ch">Bernie Hoeneisen</a>
    78   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
    79   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    80   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    81   * @version $Id: DefaultTurbineRunData.java 1066938 2011-02-03 20:14:53Z ludwig $
    82   */
    83  public class DefaultTurbineRunData
    84          extends DefaultPipelineData
    85          implements TurbineRunData, Recyclable
    86  {
    87      /**
    88       * The disposed flag.
    89       */
    90      private boolean disposed;
    91
    92      /** The default locale. */
    93      private static Locale defaultLocale = null;
    94
    95      /** The default charset. */
    96      private static String defaultCharSet = null;
    97
    98      /** A reference to the GET/POST data parser. */
    99      private ParameterParser parameters;
    100
    101     /** A reference to a cookie parser. */
    102     public CookieParser cookies;
    103
    104     /** The servlet request interface. */
    105     private HttpServletRequest req;
    106
    107     /** The servlet response interface. */
    108     private HttpServletResponse res;
    109
    110     /** The servlet configuration. */
    111     private ServletConfig config;
    112
    113     /**
    114      * The servlet context information.
    115      * Note that this is from the "Turbine" Servlet context.
    116      */
    117     private ServletContext servletContext;
    118
    119     /** The access control list. */
    120     private AccessControlList acl;
    121
    122     /** Determines if there is information in the document or not. */
    123     private boolean pageSet;
    124
    125     /** This creates an ECS Document. */
    126     private Document page;
    127
    128     /** Cached action name to execute for this request. */
    129     private String action;
    130
    131     /** This is the layout that the page will use to render the screen. */
    132     private String layout;
    133
    134     /** Cached screen name to execute for this request. */
    135     private String screen;
    136
    137     /** The character encoding of template files. */
    138     private String templateEncoding;
    139
    140     /** Information used by a Template system (such as Velocity/JSP). */
    141     private TemplateInfo templateInfo;
    142
    143     /** This is where output messages from actions should go. */
    144     private StringElement message;
    145
    146     /**
    147      * This is a dedicated message class where output messages from
    148      * actions should go.
    149      */
    150     private FormMessages messages;
    151
    152     /** The user object. */
    153     private User user;
    154
    155     /** This is what will build the <title></title> of the document. */
    156     private String title;
    157
    158     /** Determines if there is information in the outputstream or not. */
    159     private boolean outSet;
    160
    161     /**
    162      * Cache the output stream because it can be used in many
    163      * different places.
    164      */
    165     private PrintWriter out;
    166
    167     /** The locale. */
    168     private Locale locale;
    169
    170     /** The HTTP charset. */
    171     private String charSet;
    172
    173     /** The HTTP content type to return. */
    174     private String contentType = "text/html";
    175
    176     /** If this is set, also set the status code to 302. */
    177     private String redirectURI;
    178
    179     /** The HTTP status code to return. */
    180     private int statusCode = HttpServletResponse.SC_OK;
    181
    182     /** This is a List to hold critical system errors. */
    183     private List<SystemError> errors = new ArrayList<SystemError>();
    184
    185     /** JNDI Contexts. */
    186     private Map<String, Context> jndiContexts;
    187
    188     /** Holds ServerData (basic properties) about this RunData object. */
    189     private ServerData serverData;
    190
    191     /** @see #getRemoteAddr() */
    192     private String remoteAddr;
    193
    194     /** @see #getRemoteHost() */
    195     private String remoteHost;
    196
    197     /** @see #getUserAgent() */
    198     private String userAgent;
    199
    200     /** A holder for stack trace. */
    201     private String stackTrace;
    202
    203     /** A holder ofr stack trace exception. */
    204     private Throwable stackTraceException;
    205
    206     /**
    207      * Put things here and they will be shown on the default Error
    208      * screen.  This is great for debugging variable values when an
    209      * exception is thrown.
    210      */
    211     private Map<String, Object> debugVariables = new HashMap<String, Object>();
    212
    213     /** Logging */
    214     private static Log log = LogFactory.getLog(DefaultTurbineRunData.class);
    215
    216     /**
    217      * Attempts to get the User object from the session.  If it does
    218      * not exist, it returns null.
    219      *
    220      * @param session An HttpSession.
    221      * @return A User.
    222      */
    223     public static User getUserFromSession(HttpSession session)
    224     {
    225         try
    226         {
    227             return (User) session.getAttribute(User.SESSION_KEY);
    228         }
    229         catch (ClassCastException e)
    230         {
    231             return null;
    232         }
    233     }
    234
    235     /**
    236      * Allows one to invalidate the user in a session.
    237      *
    238      * @param session An HttpSession.
    239      * @return True if user was invalidated.
    240      */
    241     public static boolean removeUserFromSession(HttpSession session)
    242     {
    243         try
    244         {
    245             session.removeAttribute(User.SESSION_KEY);
    246         }
    247         catch (Exception e)
    248         {
    249             return false;
    250         }
    251         return true;
    252     }
    253
    254     /**
    255      * Gets the default locale defined by properties named
    256      * "locale.default.lang" and "locale.default.country".
    257      *
    258      * This changed from earlier Turbine versions that you can
    259      * rely on getDefaultLocale() to never return null.
    260      *
    261      * @return A Locale object.
    262      */
    263     protected static Locale getDefaultLocale()
    264     {
    265         if (defaultLocale == null)
    266         {
    267             /* Get the default locale and cache it in a static variable. */
    268             String lang = Turbine.getConfiguration()
    269                 .getString(TurbineConstants.LOCALE_DEFAULT_LANGUAGE_KEY,
    270                     TurbineConstants.LOCALE_DEFAULT_LANGUAGE_DEFAULT);
    271
    272             String country = Turbine.getConfiguration()
    273                 .getString(TurbineConstants.LOCALE_DEFAULT_COUNTRY_KEY,
    274                     TurbineConstants.LOCALE_DEFAULT_COUNTRY_DEFAULT);
    275
    276
    277             // We ensure that lang and country is never null
    278             defaultLocale =  new Locale(lang, country);
    279         }
    280         return defaultLocale;
    281     }
    282
    283     /**
    284      * Gets the default charset defined by a property named
    285      * "locale.default.charset" or by the specified locale.
    286      * If the specified locale is null, the default locale is applied.
    287      *
    288      * @return the name of the default charset or null.
    289      */
    290     protected String getDefaultCharSet()
    291     {
    292         log.debug("getDefaultCharSet()");
    293
    294         if (defaultCharSet == null)
    295         {
    296             /* Get the default charset and cache it in a static variable. */
    297             defaultCharSet = Turbine.getConfiguration()
    298                 .getString(TurbineConstants.LOCALE_DEFAULT_CHARSET_KEY,
    299                     TurbineConstants.LOCALE_DEFAULT_CHARSET_DEFAULT);
    300             log.debug("defaultCharSet = " + defaultCharSet + " (From Properties)");
    301         }
    302
    303         String charset = defaultCharSet;
    304
    305         if (StringUtils.isEmpty(charset))
    306         {
    307             log.debug("charset is empty!");
    308             /* Default charset isn't specified, get the locale specific one. */
    309             Locale locale = this.locale;
    310             if (locale == null)
    311             {
    312                 locale = getDefaultLocale();
    313                 log.debug("Locale was null, is now " + locale + " (from getDefaultLocale())");
    314             }
    315
    316             log.debug("Locale is " + locale);
    317
    318             if (!locale.equals(Locale.US))
    319             {
    320                 log.debug("We don't have US Locale!");
    321                 ServiceManager serviceManager = TurbineServices.getInstance();
    322 				MimeTypeService mimeTypeService=null;
    323                 try {
    324 					mimeTypeService= (MimeTypeService)serviceManager.getService(MimeTypeService.ROLE);
    325                 }
    326                 catch (Exception e){
    327                     throw new RuntimeException(e);
    328                 }
    329                 charset = mimeTypeService.getCharSet(locale);
    330
    331                 log.debug("Charset now " + charset);
    332             }
    333         }
    334
    335         log.debug("Returning default Charset of " + charset);
    336         return charset;
    337     }
    338
    339     /**
    340      * Constructs a run data object.
    341      */
    342     public DefaultTurbineRunData()
    343     {
    344         super();
    345         recycle();
    346     }
    347
    348     /**
    349      * Recycles the object by removing its disposed flag.
    350      */
    351     public void recycle()
    352     {
    353         disposed = false;
    354     }
    355
    356     /**
    357      * Disposes a run data object.
    358      */
    359     public void dispose()
    360     {
    361         parameters = null;
    362         cookies = null;
    363         req = null;
    364         res = null;
    365         config = null;
    366         servletContext = null;
    367         acl = null;
    368         pageSet = false;
    369         page = null;
    370         action = null;
    371         layout = null;
    372         screen = null;
    373         templateEncoding = null;
    374         templateInfo = null;
    375         message = null;
    376         messages = null;
    377         user = null;
    378         title = null;
    379         outSet = false;
    380         out = null;
    381         locale = null;
    382         charSet = null;
    383         contentType = "text/html";
    384         redirectURI = null;
    385         statusCode = HttpServletResponse.SC_OK;
    386         errors.clear();
    387         jndiContexts = null;
    388         serverData = null;
    389         remoteAddr = null;
    390         remoteHost = null;
    391         userAgent = null;
    392         stackTrace = null;
    393         stackTraceException = null;
    394         debugVariables.clear();
    395     }
    396
    397     // ***************************************
    398     // Implementation of the RunData interface
    399     // ***************************************
    400
    401     /**
    402      * Gets the parameters.
    403      *
    404      * @return a parameter parser.
    405      */
    406     public ParameterParser getParameters()
    407     {
    408         // Parse the parameters first, if not yet done.
    409         if ((this.parameters != null) &&
    410                 (this.parameters.getRequest() != this.req))
    411         {
    412             this.parameters.setRequest(this.req);
    413         }
    414         return this.parameters;
    415     }
    416
    417     /**
    418      * Gets the cookies.
    419      *
    420      * @return a cookie parser.
    421      */
    422     public CookieParser getCookies()
    423     {
    424         // Parse the cookies first, if not yet done.
    425         if ((this.cookies != null) &&
    426                 (this.cookies.getRequest() != getRequest()))
    427         {
    428             this.cookies.setData(getRequest(), getResponse());
    429         }
    430         return this.cookies;
    431     }
    432
    433     /**
    434      * Gets the servlet request.
    435      *
    436      * @return the request.
    437      */
    438     public HttpServletRequest getRequest()
    439     {
    440         return this.req;
    441     }
    442
    443     /**
    444      * Gets the servlet response.
    445      *
    446      * @return the response.
    447      */
    448     public HttpServletResponse getResponse()
    449     {
    450         return this.res;
    451     }
    452
    453     /**
    454      * Gets the servlet session information.
    455      *
    456      * @return the session.
    457      */
    458     public HttpSession getSession()
    459     {
    460         return getRequest().getSession();
    461     }
    462
    463     /**
    464      * Gets the servlet configuration used during servlet init.
    465      *
    466      * @return the configuration.
    467      */
    468     public ServletConfig getServletConfig()
    469     {
    470         return this.config;
    471     }
    472
    473     /**
    474      * Gets the servlet context used during servlet init.
    475      *
    476      * @return the context.
    477      */
    478     public ServletContext getServletContext()
    479     {
    480         return this.servletContext;
    481     }
    482
    483     /**
    484      * Gets the access control list.
    485      *
    486      * @return the access control list.
    487      */
    488     public AccessControlList getACL()
    489     {
    490         return acl;
    491     }
    492
    493     /**
    494      * Sets the access control list.
    495      *
    496      * @param acl an access control list.
    497      */
    498     public void setACL(AccessControlList acl)
    499     {
    500         this.acl = acl;
    501     }
    502
    503     /**
    504      * Checks to see if the page is set.
    505      *
    506      * @return true if the page is set.
    507      * @deprecated no replacement planned, ECS is no longer a requirement
    508      */
    509     @Deprecated
    510     public boolean isPageSet()
    511     {
    512         return pageSet;
    513     }
    514
    515     /**
    516      * Gets the page.
    517      *
    518      * @return a document.
    519      * @deprecated no replacement planned, ECS is no longer a requirement
    520      */
    521     @Deprecated
    522     public Document getPage()
    523     {
    524         pageSet = true;
    525         if (this.page == null)
    526         {
    527             this.page = new Document();
    528         }
    529         return this.page;
    530     }
    531
    532     /**
    533      * Whether or not an action has been defined.
    534      *
    535      * @return true if an action has been defined.
    536      */
    537     public boolean hasAction()
    538     {
    539         return (StringUtils.isNotEmpty(this.action)
    540           && !this.action.equalsIgnoreCase("null"));
    541     }
    542
    543     /**
    544      * Gets the action. It returns an empty string if null so
    545      * that it is easy to do conditionals on it based on the
    546      * equalsIgnoreCase() method.
    547      *
    548      * @return a string, "" if null.
    549      */
    550     public String getAction()
    551     {
    552         return (hasAction() ? this.action : "");
    553     }
    554
    555     /**
    556      * Sets the action for the request.
    557      *
    558      * @param action a atring.
    559      */
    560     public void setAction(String action)
    561     {
    562         this.action = action;
    563     }
    564
    565     /**
    566      * If the Layout has not been defined by the screen then set the
    567      * layout to be "DefaultLayout".  The screen object can also
    568      * override this method to provide intelligent determination of
    569      * the Layout to execute.  You can also define that logic here as
    570      * well if you want it to apply on a global scale.  For example,
    571      * if you wanted to allow someone to define layout "preferences"
    572      * where they could dynamicially change the layout for the entire
    573      * site.
    574      *
    575      * @return a string.
    576      */
    577
    578     public String getLayout()
    579     {
    580         if (this.layout == null)
    581         {
    582             /*
    583              * This will return something if the template
    584              * services are running. If we get nothing we
    585              * will fall back to the ECS layout.
    586              */
    587             layout = TurbineTemplate.getDefaultLayoutName(this);
    588
    589             if (layout == null)
    590             {
    591                 layout = "DefaultLayout";
    592             }
    593         }
    594
    595         return this.layout;
    596     }
    597
    598     /**
    599      * Set the layout for the request.
    600      *
    601      * @param layout a string.
    602      */
    603     public void setLayout(String layout)
    604     {
    605         this.layout = layout;
    606     }
    607
    608     /**
    609      * Convenience method for a template info that
    610      * returns the layout template being used.
    611      *
    612      * @return a string.
    613      */
    614     public String getLayoutTemplate()
    615     {
    616         return getTemplateInfo().getLayoutTemplate();
    617     }
    618
    619     /**
    620      * Modifies the layout template for the screen. This convenience
    621      * method allows for a layout to be modified from within a
    622      * template. For example;
    623      *
    624      *    $data.setLayoutTemplate("NewLayout.vm")
    625      *
    626      * @param layout a layout template.
    627      */
    628     public void setLayoutTemplate(String layout)
    629     {
    630         getTemplateInfo().setLayoutTemplate(layout);
    631     }
    632
    633     /**
    634      * Whether or not a screen has been defined.
    635      *
    636      * @return true if a screen has been defined.
    637      */
    638     public boolean hasScreen()
    639     {
    640         return StringUtils.isNotEmpty(this.screen);
    641     }
    642
    643     /**
    644      * Gets the screen to execute.
    645      *
    646      * @return a string.
    647      */
    648     public String getScreen()
    649     {
    650         return (hasScreen() ? this.screen : "");
    651     }
    652
    653     /**
    654      * Sets the screen for the request.
    655      *
    656      * @param screen a string.
    657      */
    658     public void setScreen(String screen)
    659     {
    660         this.screen = screen;
    661     }
    662
    663     /**
    664      * Convenience method for a template info that
    665      * returns the name of the template being used.
    666      *
    667      * @return a string.
    668      */
    669     public String getScreenTemplate()
    670     {
    671         return getTemplateInfo().getScreenTemplate();
    672     }
    673
    674     /**
    675      * Sets the screen template for the request. For
    676      * example;
    677      *
    678      *    $data.setScreenTemplate("NewScreen.vm")
    679      *
    680      * @param screen a screen template.
    681      */
    682     public void setScreenTemplate(String screen)
    683     {
    684         getTemplateInfo().setScreenTemplate(screen);
    685     }
    686
    687     /**
    688      * Gets the character encoding to use for reading template files.
    689      *
    690      * @return the template encoding or null if not specified.
    691      */
    692     public String getTemplateEncoding()
    693     {
    694         return templateEncoding;
    695     }
    696
    697     /**
    698      * Sets the character encoding to use for reading template files.
    699      *
    700      * @param encoding the template encoding.
    701      */
    702     public void setTemplateEncoding(String encoding)
    703     {
    704         templateEncoding = encoding;
    705     }
    706
    707     /**
    708      * Gets the template info. Creates a new one if needed.
    709      *
    710      * @return a template info.
    711      */
    712     public TemplateInfo getTemplateInfo()
    713     {
    714         if (templateInfo == null)
    715         {
    716             templateInfo = new TemplateInfo(this);
    717         }
    718         return templateInfo;
    719     }
    720
    721     /**
    722      * Whether or not a message has been defined.
    723      *
    724      * @return true if a message has been defined.
    725      */
    726     public boolean hasMessage()
    727     {
    728         return (this.message != null)
    729             && StringUtils.isNotEmpty(this.message.toString());
    730     }
    731
    732     /**
    733      * Gets the results of an action or another message
    734      * to be displayed as a string.
    735      *
    736      * @return a string.
    737      */
    738     public String getMessage()
    739     {
    740         return (this.message == null ? null : this.message.toString());
    741     }
    742
    743     /**
    744      * Sets the message for the request as a string.
    745      *
    746      * @param msg a string.
    747      */
    748     public void setMessage(String msg)
    749     {
    750         this.message = new StringElement(msg);
    751     }
    752
    753     /**
    754      * Adds the string to message. If message has prior messages from
    755      * other actions or screens, this method can be used to chain them.
    756      *
    757      * @param msg a string.
    758      */
    759     public void addMessage(String msg)
    760     {
    761         addMessage(new StringElement(msg));
    762     }
    763
    764     /**
    765      * Gets the results of an action or another message
    766      * to be displayed as an ECS string element.
    767      *
    768      * @return a string element.
    769      */
    770     public StringElement getMessageAsHTML()
    771     {
    772         return this.message;
    773     }
    774
    775     /**
    776      * Sets the message for the request as an ECS element.
    777      *
    778      * @param msg an element.
    779      */
    780     public void setMessage(Element msg)
    781     {
    782         this.message = new StringElement(msg);
    783     }
    784
    785     /**
    786      * Adds the ECS element to message. If message has prior messages from
    787      * other actions or screens, this method can be used to chain them.
    788      *
    789      * @param msg an element.
    790      */
    791     public void addMessage(Element msg)
    792     {
    793         if (msg != null)
    794         {
    795             if (message != null)
    796             {
    797                 message.addElement(msg);
    798             }
    799             else
    800             {
    801                 message = new StringElement(msg);
    802             }
    803         }
    804     }
    805
    806     /**
    807      * Unsets the message for the request.
    808      */
    809     public void unsetMessage()
    810     {
    811         this.message = null;
    812     }
    813
    814     /**
    815      * Gets a FormMessages object where all the messages to the
    816      * user should be stored.
    817      *
    818      * @return a FormMessages.
    819      */
    820     public FormMessages getMessages()
    821     {
    822         if (this.messages == null)
    823         {
    824             this.messages = new FormMessages();
    825         }
    826         return this.messages;
    827     }
    828
    829     /**
    830      * Sets the FormMessages object for the request.
    831      *
    832      * @param msgs A FormMessages.
    833      */
    834     public void setMessages(FormMessages msgs)
    835     {
    836         this.messages = msgs;
    837     }
    838
    839     /**
    840      * Gets the title of the page.
    841      *
    842      * @return a string.
    843      */
    844     public String getTitle()
    845     {
    846         return (this.title == null ? "" : this.title);
    847     }
    848
    849     /**
    850      * Sets the title of the page.
    851      *
    852      * @param title a string.
    853      */
    854     public void setTitle(String title)
    855     {
    856         this.title = title;
    857     }
    858
    859     /**
    860      * Checks if a user exists in this session.
    861      *
    862      * @return true if a user exists in this session.
    863      */
    864     public boolean userExists()
    865     {
    866         user = getUserFromSession();
    867         return (user != null);
    868     }
    869
    870     /**
    871      * Gets the user.
    872      *
    873      * @return a user.
    874      */
    875     public User getUser()
    876     {
    877         return this.user;
    878     }
    879
    880     /**
    881      * Sets the user.
    882      *
    883      * @param user a user.
    884      */
    885     public void setUser(User user)
    886     {
    887         log.debug("user set: " + user.getName());
    888         this.user = user;
    889     }
    890
    891     /**
    892      * Attempts to get the user from the session. If it does
    893      * not exist, it returns null.
    894      *
    895      * @return a user.
    896      */
    897     public User getUserFromSession()
    898     {
    899         return getUserFromSession(getSession());
    900     }
    901
    902     /**
    903      * Allows one to invalidate the user in the default session.
    904      *
    905      * @return true if user was invalidated.
    906      */
    907     public boolean removeUserFromSession()
    908     {
    909         return removeUserFromSession(getSession());
    910     }
    911
    912     /**
    913      * Checks to see if out is set.
    914      *
    915      * @return true if out is set.
    916      * @deprecated no replacement planned, response writer will not be cached
    917      */
    918     @Deprecated
    919     public boolean isOutSet()
    920     {
    921         return outSet;
    922     }
    923
    924     /**
    925      * Gets the print writer. First time calling this
    926      * will set the print writer via the response.
    927      *
    928      * @return a print writer.
    929      * @throws IOException
    930      * @deprecated no replacement planned, response writer will not be cached
    931      */
    932     @Deprecated
    933     public PrintWriter getOut()
    934             throws IOException
    935     {
    936         // Check to see if null first.
    937         if (this.out == null)
    938         {
    939             setOut(res.getWriter());
    940         }
    941         pageSet = false;
    942         outSet = true;
    943         return this.out;
    944     }
    945
    946     /**
    947      * Declares that output will be direct to the response stream,
    948      * even though getOut() may never be called.  Useful for response
    949      * mechanisms that may call res.getWriter() themselves
    950      * (such as JSP.)
    951      */
    952     public void declareDirectResponse()
    953     {
    954         outSet = true;
    955         pageSet = false;
    956     }
    957
    958     /**
    959      * Gets the locale. If it has not already been defined with
    960      * setLocale(), then  properties named "locale.default.lang"
    961      * and "locale.default.country" are checked from the Resource
    962      * Service and the corresponding locale is returned. If these
    963      * properties are undefined, JVM's default locale is returned.
    964      *
    965      * @return the locale.
    966      */
    967     public Locale getLocale()
    968     {
    969         Locale locale = this.locale;
    970         if (locale == null)
    971         {
    972             locale = getDefaultLocale();
    973         }
    974         return locale;
    975     }
    976
    977     /**
    978      * Sets the locale.
    979      *
    980      * @param locale the new locale.
    981      */
    982     public void setLocale(Locale locale)
    983     {
    984         this.locale = locale;
    985
    986         // propagate the locale to the parsers
    987         if (this.parameters != null)
    988         {
    989             parameters.setLocale(locale);
    990         }
    991
    992         if (this.cookies != null)
    993         {
    994             cookies.setLocale(locale);
    995         }
    996     }
    997
    998     /**
    999      * Gets the charset. If it has not already been defined with
    1000      * setCharSet(), then a property named "locale.default.charset"
    1001      * is checked from the Resource Service and returned. If this
    1002      * property is undefined, the default charset of the locale
    1003      * is returned. If the locale is undefined, null is returned.
    1004      *
    1005      * @return the name of the charset or null.
    1006      */
    1007     public String getCharSet()
    1008     {
    1009         log.debug("getCharSet()");
    1010
    1011         if (StringUtils.isEmpty(charSet))
    1012         {
    1013             log.debug("Charset was null!");
    1014             return getDefaultCharSet();
    1015         }
    1016         else
    1017         {
    1018             return charSet;
    1019         }
    1020     }
    1021
    1022     /**
    1023      * Sets the charset.
    1024      *
    1025      * @param charSet the name of the new charset.
    1026      */
    1027     public void setCharSet(String charSet)
    1028     {
    1029         log.debug("setCharSet(" + charSet + ")");
    1030         this.charSet = charSet;
    1031     }
    1032
    1033     /**
    1034      * Gets the HTTP content type to return. If a charset
    1035      * has been specified, it is included in the content type.
    1036      * If the charset has not been specified and the main type
    1037      * of the content type is "text", the default charset is
    1038      * included. If the default charset is undefined, but the
    1039      * default locale is defined and it is not the US locale,
    1040      * a locale specific charset is included.
    1041      *
    1042      * @return the content type or an empty string.
    1043      */
    1044     public String getContentType()
    1045     {
    1046         if (StringUtils.isNotEmpty(contentType))
    1047         {
    1048             if (StringUtils.isEmpty(charSet))
    1049             {
    1050                 if (contentType.startsWith("text/"))
    1051                 {
    1052                     return contentType + "; charset=" + getDefaultCharSet();
    1053                 }
    1054
    1055                 return contentType;
    1056             }
    1057             else
    1058             {
    1059                 return contentType + "; charset=" + charSet;
    1060             }
    1061         }
    1062
    1063         return "";
    1064     }
    1065
    1066     /**
    1067      * Sets the HTTP content type to return.
    1068      *
    1069      * @param contentType a string.
    1070      */
    1071     public void setContentType(String contentType)
    1072     {
    1073         this.contentType = contentType;
    1074     }
    1075
    1076     /**
    1077      * Gets the redirect URI. If this is set, also make sure to set
    1078      * the status code to 302.
    1079      *
    1080      * @return a string, "" if null.
    1081      */
    1082     public String getRedirectURI()
    1083     {
    1084         return (this.redirectURI == null ? "" : redirectURI);
    1085     }
    1086
    1087     /**
    1088      * Sets the redirect uri. If this is set, also make sure to set
    1089      * the status code to 302.
    1090      *
    1091      * @param ruri a string.
    1092      */
    1093     public void setRedirectURI(String ruri)
    1094     {
    1095         this.redirectURI = ruri;
    1096     }
    1097
    1098     /**
    1099      * Gets the HTTP status code to return.
    1100      *
    1101      * @return the status.
    1102      */
    1103     public int getStatusCode()
    1104     {
    1105         return statusCode;
    1106     }
    1107
    1108     /**
    1109      * Sets the HTTP status code to return.
    1110      *
    1111      * @param statusCode the status.
    1112      */
    1113     public void setStatusCode(int statusCode)
    1114     {
    1115         this.statusCode = statusCode;
    1116     }
    1117
    1118     /**
    1119      * Gets an array of system errors.
    1120      *
    1121      * @return a SystemError[].
    1122      */
    1123     public SystemError[] getSystemErrors()
    1124     {
    1125         SystemError[] result = new SystemError[errors.size()];
    1126         errors.toArray(result);
    1127         return result;
    1128     }
    1129
    1130     /**
    1131      * Adds a critical system error.
    1132      *
    1133      * @param err a system error.
    1134      */
    1135     public void setSystemError(SystemError err)
    1136     {
    1137         this.errors.add(err);
    1138     }
    1139
    1140     /**
    1141      * Gets JNDI Contexts.
    1142      *
    1143      * @return a hashtable.
    1144      */
    1145     public Map<String, Context> getJNDIContexts()
    1146     {
    1147         if (jndiContexts == null)
    1148             jndiContexts = new HashMap<String, Context>();
    1149         return jndiContexts;
    1150     }
    1151
    1152     /**
    1153      * Sets JNDI Contexts.
    1154      *
    1155      * @param contexts a hashtable.
    1156      */
    1157     public void setJNDIContexts(Map<String, Context> contexts)
    1158     {
    1159         this.jndiContexts = contexts;
    1160     }
    1161
    1162     /**
    1163      * Gets the cached server scheme.
    1164      *
    1165      * @return a string.
    1166      */
    1167     public String getServerScheme()
    1168     {
    1169         return getServerData().getServerScheme();
    1170     }
    1171
    1172     /**
    1173      * Gets the cached server name.
    1174      *
    1175      * @return a string.
    1176      */
    1177     public String getServerName()
    1178     {
    1179         return getServerData().getServerName();
    1180     }
    1181
    1182     /**
    1183      * Gets the cached server port.
    1184      *
    1185      * @return an int.
    1186      */
    1187     public int getServerPort()
    1188     {
    1189         return getServerData().getServerPort();
    1190     }
    1191
    1192     /**
    1193      * Gets the cached context path.
    1194      *
    1195      * @return a string.
    1196      */
    1197     public String getContextPath()
    1198     {
    1199         return getServerData().getContextPath();
    1200     }
    1201
    1202     /**
    1203      * Gets the cached script name.
    1204      *
    1205      * @return a string.
    1206      */
    1207     public String getScriptName()
    1208     {
    1209         return getServerData().getScriptName();
    1210     }
    1211
    1212     /**
    1213      * Gets the server data ofy the request.
    1214      *
    1215      * @return server data.
    1216      */
    1217     public ServerData getServerData()
    1218     {
    1219         return this.serverData;
    1220     }
    1221
    1222     /**
    1223      * Gets the IP address of the client that sent the request.
    1224      *
    1225      * @return a string.
    1226      */
    1227     public String getRemoteAddr()
    1228     {
    1229         if (this.remoteAddr == null)
    1230         {
    1231             this.remoteAddr = this.getRequest().getRemoteAddr();
    1232         }
    1233
    1234         return this.remoteAddr;
    1235     }
    1236
    1237     /**
    1238      * Gets the qualified name of the client that sent the request.
    1239      *
    1240      * @return a string.
    1241      */
    1242     public String getRemoteHost()
    1243     {
    1244         if (this.remoteHost == null)
    1245         {
    1246             this.remoteHost = this.getRequest().getRemoteHost();
    1247         }
    1248
    1249         return this.remoteHost;
    1250     }
    1251
    1252     /**
    1253      * Get the user agent for the request. The semantics here
    1254      * are muddled because RunData caches the value after the
    1255      * first invocation. This is different e.g. from getCharSet().
    1256      *
    1257      * @return a string.
    1258      */
    1259     public String getUserAgent()
    1260     {
    1261         if (StringUtils.isEmpty(userAgent))
    1262         {
    1263             userAgent = this.getRequest().getHeader("User-Agent");
    1264         }
    1265
    1266         return userAgent;
    1267     }
    1268
    1269     /**
    1270      * Pulls a user object from the session and increments the access
    1271      * counter and sets the last access date for the object.
    1272      */
    1273     public void populate()
    1274     {
    1275         user = getUserFromSession();
    1276
    1277         if (user != null)
    1278         {
    1279             user.setLastAccessDate();
    1280             user.incrementAccessCounter();
    1281             user.incrementAccessCounterForSession();
    1282         }
    1283     }
    1284
    1285     /**
    1286      * Saves a user object into the session.
    1287      */
    1288     public void save()
    1289     {
    1290         getSession().setAttribute(User.SESSION_KEY, user);
    1291     }
    1292
    1293     /**
    1294      * Gets the stack trace if set.
    1295      *
    1296      * @return the stack trace.
    1297      */
    1298     public String getStackTrace()
    1299     {
    1300         return stackTrace;
    1301     }
    1302
    1303     /**
    1304      * Gets the stack trace exception if set.
    1305      *
    1306      * @return the stack exception.
    1307      */
    1308     public Throwable getStackTraceException()
    1309     {
    1310         return stackTraceException;
    1311     }
    1312
    1313     /**
    1314      * Sets the stack trace.
    1315      *
    1316      * @param trace the stack trace.
    1317      * @param exp the exception.
    1318      */
    1319     public void setStackTrace(String trace, Throwable exp)
    1320     {
    1321         stackTrace = trace;
    1322         stackTraceException = exp;
    1323     }
    1324
    1325     /**
    1326      * Gets a Map of debug variables.
    1327      *
    1328      * @return a Map of debug variables.
    1329      * @deprecated use {@link #getDebugVariables} instead
    1330      */
    1331     @Deprecated
    1332     public Map<String, Object> getVarDebug()
    1333     {
    1334         return debugVariables;
    1335     }
    1336
    1337     /**
    1338      * Sets a name/value pair in an internal Map that is accessible from the
    1339      * Error screen.  This is a good way to get debugging information
    1340      * when an exception is thrown.
    1341      *
    1342      * @param name name of the variable
    1343      * @param value value of the variable.
    1344      */
    1345     public void setDebugVariable(String name, Object value)
    1346     {
    1347         this.debugVariables.put(name, value);
    1348     }
    1349
    1350     /**
    1351      * Gets a Map of debug variables.
    1352      *
    1353      * @return a Map of debug variables.
    1354      */
    1355     public Map<String, Object> getDebugVariables()
    1356     {
    1357         return this.debugVariables;
    1358     }
    1359
    1360     // **********************************************
    1361     // Implementation of the TurbineRunData interface
    1362     // **********************************************
    1363
    1364     /**
    1365      * Gets the parameter parser without parsing the parameters.
    1366      *
    1367      * @return the parameter parser.
    1368      * @todo Does this method make sense? Pulling the parameter out of
    1369      *       the run data object before setting a request (which happens
    1370      *       only in getParameters() leads to the Parameter parser having
    1371      *       no object and thus the default or even an undefined encoding
    1372      *       instead of the actual request character encoding).
    1373      */
    1374     public ParameterParser getParameterParser()
    1375     {
    1376         return parameters;
    1377     }
    1378
    1379     /**
    1380      * Sets the parameter parser.
    1381      *
    1382      * @param parser a parameter parser.
    1383      */
    1384     public void setParameterParser(ParameterParser parser)
    1385     {
    1386         parameters = parser;
    1387     }
    1388
    1389     /**
    1390      * Gets the cookie parser without parsing the cookies.
    1391      *
    1392      * @return the cookie parser.
    1393      */
    1394     public CookieParser getCookieParser()
    1395     {
    1396         return cookies;
    1397     }
    1398
    1399     /**
    1400      * Sets the cookie parser.
    1401      *
    1402      * @param parser a cookie parser.
    1403      */
    1404     public void setCookieParser(CookieParser parser)
    1405     {
    1406         cookies = parser;
    1407     }
    1408
    1409     /**
    1410      * Sets the servlet request.
    1411      *
    1412      * @param req a request.
    1413      */
    1414     public void setRequest(HttpServletRequest req)
    1415     {
    1416         this.req = req;
    1417     }
    1418
    1419     /**
    1420      * Sets the servlet response.
    1421      *
    1422      * @param res a response.
    1423      */
    1424     public void setResponse(HttpServletResponse res)
    1425     {
    1426         this.res = res;
    1427     }
    1428
    1429     /**
    1430      * Sets the servlet configuration used during servlet init.
    1431      *
    1432      * @param config a configuration.
    1433      */
    1434     public void setServletConfig(ServletConfig config)
    1435     {
    1436         this.config = config;
    1437         if (config == null)
    1438         {
    1439             this.servletContext = null;
    1440         }
    1441         else
    1442         {
    1443             this.servletContext = config.getServletContext();
    1444         }
    1445     }
    1446
    1447     /**
    1448      * Sets the server data of the request.
    1449      *
    1450      * @param serverData server data.
    1451      */
    1452     public void setServerData(ServerData serverData)
    1453     {
    1454         this.serverData = serverData;
    1455     }
    1456
    1457     // ********************
    1458     // Miscellanous setters
    1459     // ********************
    1460
    1461     /**
    1462      * Sets the print writer.
    1463      *
    1464      * @param out a print writer.
    1465      * @deprecated no replacement planned, response writer will not be cached
    1466      */
    1467     @Deprecated
    1468     protected void setOut(PrintWriter out)
    1469     {
    1470         this.out = out;
    1471     }
    1472
    1473     /**
    1474      * Sets the cached server scheme that is stored in the server data.
    1475      *
    1476      * @param serverScheme a string.
    1477      */
    1478     protected void setServerScheme(String serverScheme)
    1479     {
    1480         getServerData().setServerScheme(serverScheme);
    1481     }
    1482
    1483     /**
    1484      * Sets the cached server same that is stored in the server data.
    1485      *
    1486      * @param serverName a string.
    1487      */
    1488     protected void setServerName(String serverName)
    1489     {
    1490         getServerData().setServerName(serverName);
    1491     }
    1492
    1493     /**
    1494      * Sets the cached server port that is stored in the server data.
    1495      *
    1496      * @param port an int.
    1497      */
    1498     protected void setServerPort(int port)
    1499     {
    1500         getServerData().setServerPort(port);
    1501     }
    1502
    1503     /**
    1504      * Sets the cached context path that is stored in the server data.
    1505      *
    1506      * @param contextPath a string.
    1507      */
    1508     protected void setContextPath(String contextPath)
    1509     {
    1510         getServerData().setContextPath(contextPath);
    1511     }
    1512
    1513     /**
    1514      * Sets the cached script name that is stored in the server data.
    1515      *
    1516      * @param scriptName a string.
    1517      */
    1518     protected void setScriptName(String scriptName)
    1519     {
    1520         getServerData().setScriptName(scriptName);
    1521     }
    1522
    1523     /**
    1524      * Checks whether the object is disposed.
    1525      *
    1526      * @return true, if the object is disposed.
    1527      */
    1528     public boolean isDisposed()
    1529     {
    1530         return disposed;
    1531     }
    1532
    1533 }