0001: package org.apache.turbine.services.rundata;
0002:
0003: /*
0004: * Licensed to the Apache Software Foundation (ASF) under one
0005: * or more contributor license agreements. See the NOTICE file
0006: * distributed with this work for additional information
0007: * regarding copyright ownership. The ASF licenses this file
0008: * to you under the Apache License, Version 2.0 (the
0009: * "License"); you may not use this file except in compliance
0010: * with the License. You may obtain a copy of the License at
0011: *
0012: * http://www.apache.org/licenses/LICENSE-2.0
0013: *
0014: * Unless required by applicable law or agreed to in writing,
0015: * software distributed under the License is distributed on an
0016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0017: * KIND, either express or implied. See the License for the
0018: * specific language governing permissions and limitations
0019: * under the License.
0020: */
0021:
0022: import java.io.IOException;
0023: import java.io.PrintWriter;
0024:
0025: import java.util.ArrayList;
0026: import java.util.HashMap;
0027: import java.util.List;
0028: import java.util.Locale;
0029: import java.util.Map;
0030:
0031: import javax.servlet.ServletConfig;
0032: import javax.servlet.ServletContext;
0033: import javax.servlet.http.HttpServletRequest;
0034: import javax.servlet.http.HttpServletResponse;
0035: import javax.servlet.http.HttpSession;
0036:
0037: import org.apache.commons.lang.StringUtils;
0038:
0039: import org.apache.commons.logging.Log;
0040: import org.apache.commons.logging.LogFactory;
0041:
0042: import org.apache.ecs.Document;
0043: import org.apache.ecs.Element;
0044: import org.apache.ecs.StringElement;
0045:
0046: import org.apache.turbine.Turbine;
0047: import org.apache.turbine.TurbineConstants;
0048: import org.apache.turbine.om.security.User;
0049: import org.apache.turbine.services.mimetype.TurbineMimeTypes;
0050: import org.apache.turbine.services.template.TurbineTemplate;
0051: import org.apache.turbine.util.FormMessages;
0052: import org.apache.turbine.util.ServerData;
0053: import org.apache.turbine.util.SystemError;
0054: import org.apache.turbine.util.parser.CookieParser;
0055: import org.apache.turbine.util.parser.ParameterParser;
0056: import org.apache.turbine.util.pool.RecyclableSupport;
0057: import org.apache.turbine.util.security.AccessControlList;
0058: import org.apache.turbine.util.template.TemplateInfo;
0059:
0060: /**
0061: * DefaultTurbineRunData is the default implementation of the
0062: * TurbineRunData interface, which is distributed by the Turbine
0063: * RunData service, if another implementation is not defined in
0064: * the default or specified RunData configuration.
0065: * TurbineRunData is an extension to RunData, which
0066: * is an interface to run-rime information that is passed
0067: * within Turbine. This provides the threading mechanism for the
0068: * entire system because multiple requests can potentially come in
0069: * at the same time. Thus, there is only one RunData implementation
0070: * for each request that is being serviced.
0071: *
0072: * <p>DefaultTurbineRunData implements the Recyclable interface making
0073: * it possible to pool its instances for recycling.
0074: *
0075: * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
0076: * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
0077: * @author <a href="mailto:bhoeneis@ee.ethz.ch">Bernie Hoeneisen</a>
0078: * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
0079: * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
0080: * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
0081: * @version $Id: DefaultTurbineRunData.java 534527 2007-05-02 16:10:59Z tv $
0082: */
0083: public class DefaultTurbineRunData extends RecyclableSupport implements
0084: TurbineRunData {
0085: /** The default locale. */
0086: private static Locale defaultLocale = null;
0087:
0088: /** The default charset. */
0089: private static String defaultCharSet = null;
0090:
0091: /** A reference to the GET/POST data parser. */
0092: private ParameterParser parameters;
0093:
0094: /** A reference to a cookie parser. */
0095: public CookieParser cookies;
0096:
0097: /** The servlet request interface. */
0098: private HttpServletRequest req;
0099:
0100: /** The servlet response interface. */
0101: private HttpServletResponse res;
0102:
0103: /** The servlet configuration. */
0104: private ServletConfig config;
0105:
0106: /**
0107: * The servlet context information.
0108: * Note that this is from the "Turbine" Servlet context.
0109: */
0110: private ServletContext servletContext;
0111:
0112: /** The access control list. */
0113: private AccessControlList acl;
0114:
0115: /** Determines if there is information in the document or not. */
0116: private boolean pageSet;
0117:
0118: /** This creates an ECS Document. */
0119: private Document page;
0120:
0121: /** Cached action name to execute for this request. */
0122: private String action;
0123:
0124: /** This is the layout that the page will use to render the screen. */
0125: private String layout;
0126:
0127: /** Cached screen name to execute for this request. */
0128: private String screen;
0129:
0130: /** The character encoding of template files. */
0131: private String templateEncoding;
0132:
0133: /** Information used by a Template system (such as Velocity/JSP). */
0134: private TemplateInfo templateInfo;
0135:
0136: /** This is where output messages from actions should go. */
0137: private StringElement message;
0138:
0139: /**
0140: * This is a dedicated message class where output messages from
0141: * actions should go.
0142: */
0143: private FormMessages messages;
0144:
0145: /** The user object. */
0146: private User user;
0147:
0148: /** This is what will build the <title></title> of the document. */
0149: private String title;
0150:
0151: /** Determines if there is information in the outputstream or not. */
0152: private boolean outSet;
0153:
0154: /**
0155: * Cache the output stream because it can be used in many
0156: * different places.
0157: */
0158: private PrintWriter out;
0159:
0160: /** The locale. */
0161: private Locale locale;
0162:
0163: /** The HTTP charset. */
0164: private String charSet;
0165:
0166: /** The HTTP content type to return. */
0167: private String contentType = "text/html";
0168:
0169: /** If this is set, also set the status code to 302. */
0170: private String redirectURI;
0171:
0172: /** The HTTP status code to return. */
0173: private int statusCode = HttpServletResponse.SC_OK;
0174:
0175: /** This is a List to hold critical system errors. */
0176: private List errors = new ArrayList();
0177:
0178: /** JNDI Contexts. */
0179: private Map jndiContexts;
0180:
0181: /** Holds ServerData (basic properties) about this RunData object. */
0182: private ServerData serverData;
0183:
0184: /** @see #getRemoteAddr() */
0185: private String remoteAddr;
0186:
0187: /** @see #getRemoteHost() */
0188: private String remoteHost;
0189:
0190: /** @see #getUserAgent() */
0191: private String userAgent;
0192:
0193: /** A holder for stack trace. */
0194: private String stackTrace;
0195:
0196: /** A holder ofr stack trace exception. */
0197: private Throwable stackTraceException;
0198:
0199: /**
0200: * Put things here and they will be shown on the default Error
0201: * screen. This is great for debugging variable values when an
0202: * exception is thrown.
0203: */
0204: private Map debugVariables = new HashMap();
0205:
0206: /** Logging */
0207: private static Log log = LogFactory
0208: .getLog(DefaultTurbineRunData.class);
0209:
0210: /**
0211: * Attempts to get the User object from the session. If it does
0212: * not exist, it returns null.
0213: *
0214: * @param session An HttpSession.
0215: * @return A User.
0216: */
0217: public static User getUserFromSession(HttpSession session) {
0218: try {
0219: return (User) session.getAttribute(User.SESSION_KEY);
0220: } catch (ClassCastException e) {
0221: return null;
0222: }
0223: }
0224:
0225: /**
0226: * Allows one to invalidate the user in a session.
0227: *
0228: * @param session An HttpSession.
0229: * @return True if user was invalidated.
0230: */
0231: public static boolean removeUserFromSession(HttpSession session) {
0232: try {
0233: session.removeAttribute(User.SESSION_KEY);
0234: } catch (Exception e) {
0235: return false;
0236: }
0237: return true;
0238: }
0239:
0240: /**
0241: * Gets the default locale defined by properties named
0242: * "locale.default.lang" and "locale.default.country".
0243: *
0244: * This changed from earlier Turbine versions that you can
0245: * rely on getDefaultLocale() to never return null.
0246: *
0247: * @return A Locale object.
0248: */
0249: protected static Locale getDefaultLocale() {
0250: if (defaultLocale == null) {
0251: /* Get the default locale and cache it in a static variable. */
0252: String lang = Turbine.getConfiguration().getString(
0253: TurbineConstants.LOCALE_DEFAULT_LANGUAGE_KEY,
0254: TurbineConstants.LOCALE_DEFAULT_LANGUAGE_DEFAULT);
0255:
0256: String country = Turbine.getConfiguration().getString(
0257: TurbineConstants.LOCALE_DEFAULT_COUNTRY_KEY,
0258: TurbineConstants.LOCALE_DEFAULT_COUNTRY_DEFAULT);
0259:
0260: // We ensure that lang and country is never null
0261: defaultLocale = new Locale(lang, country);
0262: }
0263: return defaultLocale;
0264: }
0265:
0266: /**
0267: * Gets the default charset defined by a property named
0268: * "locale.default.charset" or by the specified locale.
0269: * If the specified locale is null, the default locale is applied.
0270: *
0271: * @return the name of the default charset or null.
0272: */
0273: protected String getDefaultCharSet() {
0274: log.debug("getDefaultCharSet()");
0275:
0276: if (defaultCharSet == null) {
0277: /* Get the default charset and cache it in a static variable. */
0278: defaultCharSet = Turbine.getConfiguration().getString(
0279: TurbineConstants.LOCALE_DEFAULT_CHARSET_KEY,
0280: TurbineConstants.LOCALE_DEFAULT_CHARSET_DEFAULT);
0281: log.debug("defaultCharSet = " + defaultCharSet
0282: + " (From Properties)");
0283: }
0284:
0285: String charset = defaultCharSet;
0286:
0287: if (StringUtils.isEmpty(charset)) {
0288: log.debug("charset is empty!");
0289: /* Default charset isn't specified, get the locale specific one. */
0290: Locale locale = this .locale;
0291: if (locale == null) {
0292: locale = getDefaultLocale();
0293: log.debug("Locale was null, is now " + locale
0294: + " (from getDefaultLocale())");
0295: }
0296:
0297: log.debug("Locale is " + locale);
0298:
0299: if (!locale.equals(Locale.US)) {
0300: log.debug("We have US Locale!");
0301: charset = TurbineMimeTypes.getCharSet(locale);
0302:
0303: log.debug("Charset now " + charset);
0304: }
0305: }
0306:
0307: log.debug("Returning default Charset of " + charset);
0308: return charset;
0309: }
0310:
0311: /**
0312: * Constructs a run data object.
0313: */
0314: public DefaultTurbineRunData() {
0315: super ();
0316: }
0317:
0318: /**
0319: * Recycles a run data object.
0320: */
0321: public void recycle() {
0322: super .recycle();
0323: }
0324:
0325: /**
0326: * Disposes a run data object.
0327: */
0328: public void dispose() {
0329: parameters = null;
0330: cookies = null;
0331: req = null;
0332: res = null;
0333: config = null;
0334: servletContext = null;
0335: acl = null;
0336: pageSet = false;
0337: page = null;
0338: action = null;
0339: layout = null;
0340: screen = null;
0341: templateEncoding = null;
0342: templateInfo = null;
0343: message = null;
0344: messages = null;
0345: user = null;
0346: title = null;
0347: outSet = false;
0348: out = null;
0349: locale = null;
0350: charSet = null;
0351: contentType = "text/html";
0352: redirectURI = null;
0353: statusCode = HttpServletResponse.SC_OK;
0354: errors.clear();
0355: jndiContexts = null;
0356: serverData = null;
0357: remoteAddr = null;
0358: remoteHost = null;
0359: userAgent = null;
0360: stackTrace = null;
0361: stackTraceException = null;
0362: debugVariables.clear();
0363:
0364: super .dispose();
0365: }
0366:
0367: // ***************************************
0368: // Implementation of the RunData interface
0369: // ***************************************
0370:
0371: /**
0372: * Gets the parameters.
0373: *
0374: * @return a parameter parser.
0375: */
0376: public ParameterParser getParameters() {
0377: // Parse the parameters first, if not yet done.
0378: if ((this .parameters != null)
0379: && (this .parameters.getRequest() != this .req)) {
0380: this .parameters.setRequest(this .req);
0381: }
0382: return this .parameters;
0383: }
0384:
0385: /**
0386: * Gets the cookies.
0387: *
0388: * @return a cookie parser.
0389: */
0390: public CookieParser getCookies() {
0391: // Parse the cookies first, if not yet done.
0392: if ((this .cookies != null)
0393: && (this .cookies.getRequest() != getRequest())) {
0394: // We deprecated the use of the RunData object in
0395: // the Cookie Parser. However, until we remove the
0396: // RunData access from the Cookie Parser, we must
0397: // of course, set the member variable in the Parser
0398: // After we removed the code, please replace the
0399: // following line with
0400: // this.cookies.setData(getRequest(), getResponse());
0401: this .cookies.setRunData(this );
0402: }
0403: return this .cookies;
0404: }
0405:
0406: /**
0407: * Gets the servlet request.
0408: *
0409: * @return the request.
0410: */
0411: public HttpServletRequest getRequest() {
0412: return this .req;
0413: }
0414:
0415: /**
0416: * Gets the servlet response.
0417: *
0418: * @return the response.
0419: */
0420: public HttpServletResponse getResponse() {
0421: return this .res;
0422: }
0423:
0424: /**
0425: * Gets the servlet session information.
0426: *
0427: * @return the session.
0428: */
0429: public HttpSession getSession() {
0430: return getRequest().getSession();
0431: }
0432:
0433: /**
0434: * Gets the servlet configuration used during servlet init.
0435: *
0436: * @return the configuration.
0437: */
0438: public ServletConfig getServletConfig() {
0439: return this .config;
0440: }
0441:
0442: /**
0443: * Gets the servlet context used during servlet init.
0444: *
0445: * @return the context.
0446: */
0447: public ServletContext getServletContext() {
0448: return this .servletContext;
0449: }
0450:
0451: /**
0452: * Gets the access control list.
0453: *
0454: * @return the access control list.
0455: */
0456: public AccessControlList getACL() {
0457: return acl;
0458: }
0459:
0460: /**
0461: * Sets the access control list.
0462: *
0463: * @param acl an access control list.
0464: */
0465: public void setACL(AccessControlList acl) {
0466: this .acl = acl;
0467: }
0468:
0469: /**
0470: * Checks to see if the page is set.
0471: *
0472: * @return true if the page is set.
0473: * @deprecated no replacement planned, ECS is no longer a requirement
0474: */
0475: public boolean isPageSet() {
0476: return pageSet;
0477: }
0478:
0479: /**
0480: * Gets the page.
0481: *
0482: * @return a document.
0483: * @deprecated no replacement planned, ECS is no longer a requirement
0484: */
0485: public Document getPage() {
0486: pageSet = true;
0487: if (this .page == null)
0488: this .page = new Document();
0489: return this .page;
0490: }
0491:
0492: /**
0493: * Whether or not an action has been defined.
0494: *
0495: * @return true if an action has been defined.
0496: */
0497: public boolean hasAction() {
0498: return (StringUtils.isNotEmpty(this .action) && !this .action
0499: .equalsIgnoreCase("null"));
0500: }
0501:
0502: /**
0503: * Gets the action. It returns an empty string if null so
0504: * that it is easy to do conditionals on it based on the
0505: * equalsIgnoreCase() method.
0506: *
0507: * @return a string, "" if null.
0508: */
0509: public String getAction() {
0510: return (hasAction() ? this .action : "");
0511: }
0512:
0513: /**
0514: * Sets the action for the request.
0515: *
0516: * @param action a atring.
0517: */
0518: public void setAction(String action) {
0519: this .action = action;
0520: }
0521:
0522: /**
0523: * If the Layout has not been defined by the screen then set the
0524: * layout to be "DefaultLayout". The screen object can also
0525: * override this method to provide intelligent determination of
0526: * the Layout to execute. You can also define that logic here as
0527: * well if you want it to apply on a global scale. For example,
0528: * if you wanted to allow someone to define layout "preferences"
0529: * where they could dynamicially change the layout for the entire
0530: * site.
0531: *
0532: * @return a string.
0533: */
0534:
0535: public String getLayout() {
0536: if (this .layout == null) {
0537: /*
0538: * This will return something if the template
0539: * services are running. If we get nothing we
0540: * will fall back to the ECS layout.
0541: */
0542: layout = TurbineTemplate.getDefaultLayoutName(this );
0543:
0544: if (layout == null) {
0545: layout = "DefaultLayout";
0546: }
0547: }
0548:
0549: return this .layout;
0550: }
0551:
0552: /**
0553: * Set the layout for the request.
0554: *
0555: * @param layout a string.
0556: */
0557: public void setLayout(String layout) {
0558: this .layout = layout;
0559: }
0560:
0561: /**
0562: * Convenience method for a template info that
0563: * returns the layout template being used.
0564: *
0565: * @return a string.
0566: */
0567: public String getLayoutTemplate() {
0568: return getTemplateInfo().getLayoutTemplate();
0569: }
0570:
0571: /**
0572: * Modifies the layout template for the screen. This convenience
0573: * method allows for a layout to be modified from within a
0574: * template. For example;
0575: *
0576: * $data.setLayoutTemplate("NewLayout.vm")
0577: *
0578: * @param layout a layout template.
0579: */
0580: public void setLayoutTemplate(String layout) {
0581: getTemplateInfo().setLayoutTemplate(layout);
0582: }
0583:
0584: /**
0585: * Whether or not a screen has been defined.
0586: *
0587: * @return true if a screen has been defined.
0588: */
0589: public boolean hasScreen() {
0590: return StringUtils.isNotEmpty(this .screen);
0591: }
0592:
0593: /**
0594: * Gets the screen to execute.
0595: *
0596: * @return a string.
0597: */
0598: public String getScreen() {
0599: return (hasScreen() ? this .screen : "");
0600: }
0601:
0602: /**
0603: * Sets the screen for the request.
0604: *
0605: * @param screen a string.
0606: */
0607: public void setScreen(String screen) {
0608: this .screen = screen;
0609: }
0610:
0611: /**
0612: * Convenience method for a template info that
0613: * returns the name of the template being used.
0614: *
0615: * @return a string.
0616: */
0617: public String getScreenTemplate() {
0618: return getTemplateInfo().getScreenTemplate();
0619: }
0620:
0621: /**
0622: * Sets the screen template for the request. For
0623: * example;
0624: *
0625: * $data.setScreenTemplate("NewScreen.vm")
0626: *
0627: * @param screen a screen template.
0628: */
0629: public void setScreenTemplate(String screen) {
0630: getTemplateInfo().setScreenTemplate(screen);
0631: }
0632:
0633: /**
0634: * Gets the character encoding to use for reading template files.
0635: *
0636: * @return the template encoding or null if not specified.
0637: */
0638: public String getTemplateEncoding() {
0639: return templateEncoding;
0640: }
0641:
0642: /**
0643: * Sets the character encoding to use for reading template files.
0644: *
0645: * @param encoding the template encoding.
0646: */
0647: public void setTemplateEncoding(String encoding) {
0648: templateEncoding = encoding;
0649: }
0650:
0651: /**
0652: * Gets the template info. Creates a new one if needed.
0653: *
0654: * @return a template info.
0655: */
0656: public TemplateInfo getTemplateInfo() {
0657: if (templateInfo == null) {
0658: templateInfo = new TemplateInfo(this );
0659: }
0660: return templateInfo;
0661: }
0662:
0663: /**
0664: * Whether or not a message has been defined.
0665: *
0666: * @return true if a message has been defined.
0667: */
0668: public boolean hasMessage() {
0669: return (this .message != null)
0670: && StringUtils.isNotEmpty(this .message.toString());
0671: }
0672:
0673: /**
0674: * Gets the results of an action or another message
0675: * to be displayed as a string.
0676: *
0677: * @return a string.
0678: */
0679: public String getMessage() {
0680: return (this .message == null ? null : this .message.toString());
0681: }
0682:
0683: /**
0684: * Sets the message for the request as a string.
0685: *
0686: * @param msg a string.
0687: */
0688: public void setMessage(String msg) {
0689: this .message = new StringElement(msg);
0690: }
0691:
0692: /**
0693: * Adds the string to message. If message has prior messages from
0694: * other actions or screens, this method can be used to chain them.
0695: *
0696: * @param msg a string.
0697: */
0698: public void addMessage(String msg) {
0699: addMessage(new StringElement(msg));
0700: }
0701:
0702: /**
0703: * Gets the results of an action or another message
0704: * to be displayed as an ECS string element.
0705: *
0706: * @return a string element.
0707: */
0708: public StringElement getMessageAsHTML() {
0709: return this .message;
0710: }
0711:
0712: /**
0713: * Sets the message for the request as an ECS element.
0714: *
0715: * @param msg an element.
0716: */
0717: public void setMessage(Element msg) {
0718: this .message = new StringElement(msg);
0719: }
0720:
0721: /**
0722: * Adds the ECS element to message. If message has prior messages from
0723: * other actions or screens, this method can be used to chain them.
0724: *
0725: * @param msg an element.
0726: */
0727: public void addMessage(Element msg) {
0728: if (msg != null) {
0729: if (message != null) {
0730: message.addElement(msg);
0731: } else {
0732: message = new StringElement(msg);
0733: }
0734: }
0735: }
0736:
0737: /**
0738: * Unsets the message for the request.
0739: */
0740: public void unsetMessage() {
0741: this .message = null;
0742: }
0743:
0744: /**
0745: * Gets a FormMessages object where all the messages to the
0746: * user should be stored.
0747: *
0748: * @return a FormMessages.
0749: */
0750: public FormMessages getMessages() {
0751: if (this .messages == null) {
0752: this .messages = new FormMessages();
0753: }
0754: return this .messages;
0755: }
0756:
0757: /**
0758: * Sets the FormMessages object for the request.
0759: *
0760: * @param msgs A FormMessages.
0761: */
0762: public void setMessages(FormMessages msgs) {
0763: this .messages = msgs;
0764: }
0765:
0766: /**
0767: * Gets the title of the page.
0768: *
0769: * @return a string.
0770: */
0771: public String getTitle() {
0772: return (this .title == null ? "" : this .title);
0773: }
0774:
0775: /**
0776: * Sets the title of the page.
0777: *
0778: * @param title a string.
0779: */
0780: public void setTitle(String title) {
0781: this .title = title;
0782: }
0783:
0784: /**
0785: * Checks if a user exists in this session.
0786: *
0787: * @return true if a user exists in this session.
0788: */
0789: public boolean userExists() {
0790: user = getUserFromSession();
0791: return (user != null);
0792: }
0793:
0794: /**
0795: * Gets the user.
0796: *
0797: * @return a user.
0798: */
0799: public User getUser() {
0800: return this .user;
0801: }
0802:
0803: /**
0804: * Sets the user.
0805: *
0806: * @param user a user.
0807: */
0808: public void setUser(User user) {
0809: log.debug("user set: " + user.getName());
0810: this .user = user;
0811: }
0812:
0813: /**
0814: * Attempts to get the user from the session. If it does
0815: * not exist, it returns null.
0816: *
0817: * @return a user.
0818: */
0819: public User getUserFromSession() {
0820: return getUserFromSession(getSession());
0821: }
0822:
0823: /**
0824: * Allows one to invalidate the user in the default session.
0825: *
0826: * @return true if user was invalidated.
0827: */
0828: public boolean removeUserFromSession() {
0829: return removeUserFromSession(getSession());
0830: }
0831:
0832: /**
0833: * Checks to see if out is set.
0834: *
0835: * @return true if out is set.
0836: * @deprecated no replacement planned, response writer will not be cached
0837: */
0838: public boolean isOutSet() {
0839: return outSet;
0840: }
0841:
0842: /**
0843: * Gets the print writer. First time calling this
0844: * will set the print writer via the response.
0845: *
0846: * @return a print writer.
0847: * @throws IOException
0848: * @deprecated no replacement planned, response writer will not be cached
0849: */
0850: public PrintWriter getOut() throws IOException {
0851: // Check to see if null first.
0852: if (this .out == null) {
0853: setOut(res.getWriter());
0854: }
0855: pageSet = false;
0856: outSet = true;
0857: return this .out;
0858: }
0859:
0860: /**
0861: * Declares that output will be direct to the response stream,
0862: * even though getOut() may never be called. Useful for response
0863: * mechanisms that may call res.getWriter() themselves
0864: * (such as JSP.)
0865: */
0866: public void declareDirectResponse() {
0867: outSet = true;
0868: pageSet = false;
0869: }
0870:
0871: /**
0872: * Gets the locale. If it has not already been defined with
0873: * setLocale(), then properties named "locale.default.lang"
0874: * and "locale.default.country" are checked from the Resource
0875: * Service and the corresponding locale is returned. If these
0876: * properties are undefined, JVM's default locale is returned.
0877: *
0878: * @return the locale.
0879: */
0880: public Locale getLocale() {
0881: Locale locale = this .locale;
0882: if (locale == null) {
0883: locale = getDefaultLocale();
0884: }
0885: return locale;
0886: }
0887:
0888: /**
0889: * Sets the locale.
0890: *
0891: * @param locale the new locale.
0892: */
0893: public void setLocale(Locale locale) {
0894: this .locale = locale;
0895: }
0896:
0897: /**
0898: * Gets the charset. If it has not already been defined with
0899: * setCharSet(), then a property named "locale.default.charset"
0900: * is checked from the Resource Service and returned. If this
0901: * property is undefined, the default charset of the locale
0902: * is returned. If the locale is undefined, null is returned.
0903: *
0904: * @return the name of the charset or null.
0905: */
0906: public String getCharSet() {
0907: log.debug("getCharSet()");
0908:
0909: if (StringUtils.isEmpty(charSet)) {
0910: log.debug("Charset was null!");
0911: return getDefaultCharSet();
0912: } else {
0913: return charSet;
0914: }
0915: }
0916:
0917: /**
0918: * Sets the charset.
0919: *
0920: * @param charSet the name of the new charset.
0921: */
0922: public void setCharSet(String charSet) {
0923: log.debug("setCharSet(" + charSet + ")");
0924: this .charSet = charSet;
0925: }
0926:
0927: /**
0928: * Gets the HTTP content type to return. If a charset
0929: * has been specified, it is included in the content type.
0930: * If the charset has not been specified and the main type
0931: * of the content type is "text", the default charset is
0932: * included. If the default charset is undefined, but the
0933: * default locale is defined and it is not the US locale,
0934: * a locale specific charset is included.
0935: *
0936: * @return the content type or an empty string.
0937: */
0938: public String getContentType() {
0939: if (StringUtils.isNotEmpty(contentType)) {
0940: if (StringUtils.isEmpty(charSet)) {
0941: if (contentType.startsWith("text/")) {
0942: return contentType + "; charset="
0943: + getDefaultCharSet();
0944: }
0945: } else {
0946: return contentType + "; charset=" + charSet;
0947: }
0948: }
0949:
0950: return "";
0951: }
0952:
0953: /**
0954: * Sets the HTTP content type to return.
0955: *
0956: * @param contentType a string.
0957: */
0958: public void setContentType(String contentType) {
0959: this .contentType = contentType;
0960: }
0961:
0962: /**
0963: * Gets the redirect URI. If this is set, also make sure to set
0964: * the status code to 302.
0965: *
0966: * @return a string, "" if null.
0967: */
0968: public String getRedirectURI() {
0969: return (this .redirectURI == null ? "" : redirectURI);
0970: }
0971:
0972: /**
0973: * Sets the redirect uri. If this is set, also make sure to set
0974: * the status code to 302.
0975: *
0976: * @param ruri a string.
0977: */
0978: public void setRedirectURI(String ruri) {
0979: this .redirectURI = ruri;
0980: }
0981:
0982: /**
0983: * Gets the HTTP status code to return.
0984: *
0985: * @return the status.
0986: */
0987: public int getStatusCode() {
0988: return statusCode;
0989: }
0990:
0991: /**
0992: * Sets the HTTP status code to return.
0993: *
0994: * @param statusCode the status.
0995: */
0996: public void setStatusCode(int statusCode) {
0997: this .statusCode = statusCode;
0998: }
0999:
1000: /**
1001: * Gets an array of system errors.
1002: *
1003: * @return a SystemError[].
1004: */
1005: public SystemError[] getSystemErrors() {
1006: SystemError[] result = new SystemError[errors.size()];
1007: errors.toArray(result);
1008: return result;
1009: }
1010:
1011: /**
1012: * Adds a critical system error.
1013: *
1014: * @param err a system error.
1015: */
1016: public void setSystemError(SystemError err) {
1017: this .errors.add(err);
1018: }
1019:
1020: /**
1021: * Gets JNDI Contexts.
1022: *
1023: * @return a hashtable.
1024: */
1025: public Map getJNDIContexts() {
1026: if (jndiContexts == null)
1027: jndiContexts = new HashMap();
1028: return jndiContexts;
1029: }
1030:
1031: /**
1032: * Sets JNDI Contexts.
1033: *
1034: * @param contexts a hashtable.
1035: */
1036: public void setJNDIContexts(Map contexts) {
1037: this .jndiContexts = contexts;
1038: }
1039:
1040: /**
1041: * Gets the cached server scheme.
1042: *
1043: * @return a string.
1044: */
1045: public String getServerScheme() {
1046: return getServerData().getServerScheme();
1047: }
1048:
1049: /**
1050: * Gets the cached server name.
1051: *
1052: * @return a string.
1053: */
1054: public String getServerName() {
1055: return getServerData().getServerName();
1056: }
1057:
1058: /**
1059: * Gets the cached server port.
1060: *
1061: * @return an int.
1062: */
1063: public int getServerPort() {
1064: return getServerData().getServerPort();
1065: }
1066:
1067: /**
1068: * Gets the cached context path.
1069: *
1070: * @return a string.
1071: */
1072: public String getContextPath() {
1073: return getServerData().getContextPath();
1074: }
1075:
1076: /**
1077: * Gets the cached script name.
1078: *
1079: * @return a string.
1080: */
1081: public String getScriptName() {
1082: return getServerData().getScriptName();
1083: }
1084:
1085: /**
1086: * Gets the server data ofy the request.
1087: *
1088: * @return server data.
1089: */
1090: public ServerData getServerData() {
1091: return this .serverData;
1092: }
1093:
1094: /**
1095: * Gets the IP address of the client that sent the request.
1096: *
1097: * @return a string.
1098: */
1099: public String getRemoteAddr() {
1100: if (this .remoteAddr == null) {
1101: this .remoteAddr = this .getRequest().getRemoteAddr();
1102: }
1103:
1104: return this .remoteAddr;
1105: }
1106:
1107: /**
1108: * Gets the qualified name of the client that sent the request.
1109: *
1110: * @return a string.
1111: */
1112: public String getRemoteHost() {
1113: if (this .remoteHost == null) {
1114: this .remoteHost = this .getRequest().getRemoteHost();
1115: }
1116:
1117: return this .remoteHost;
1118: }
1119:
1120: /**
1121: * Get the user agent for the request. The semantics here
1122: * are muddled because RunData caches the value after the
1123: * first invocation. This is different e.g. from getCharSet().
1124: *
1125: * @return a string.
1126: */
1127: public String getUserAgent() {
1128: if (StringUtils.isEmpty(userAgent)) {
1129: userAgent = this .getRequest().getHeader("User-Agent");
1130: }
1131:
1132: return userAgent;
1133: }
1134:
1135: /**
1136: * Pulls a user object from the session and increments the access
1137: * counter and sets the last access date for the object.
1138: */
1139: public void populate() {
1140: user = getUserFromSession();
1141:
1142: if (user != null) {
1143: user.setLastAccessDate();
1144: user.incrementAccessCounter();
1145: user.incrementAccessCounterForSession();
1146: }
1147: }
1148:
1149: /**
1150: * Saves a user object into the session.
1151: */
1152: public void save() {
1153: getSession().setAttribute(User.SESSION_KEY, user);
1154: }
1155:
1156: /**
1157: * Gets the stack trace if set.
1158: *
1159: * @return the stack trace.
1160: */
1161: public String getStackTrace() {
1162: return stackTrace;
1163: }
1164:
1165: /**
1166: * Gets the stack trace exception if set.
1167: *
1168: * @return the stack exception.
1169: */
1170: public Throwable getStackTraceException() {
1171: return stackTraceException;
1172: }
1173:
1174: /**
1175: * Sets the stack trace.
1176: *
1177: * @param trace the stack trace.
1178: * @param exp the exception.
1179: */
1180: public void setStackTrace(String trace, Throwable exp) {
1181: stackTrace = trace;
1182: stackTraceException = exp;
1183: }
1184:
1185: /**
1186: * Gets a Map of debug variables.
1187: *
1188: * @return a Map of debug variables.
1189: * @deprecated use {@link #getDebugVariables} instead
1190: */
1191: public Map getVarDebug() {
1192: return debugVariables;
1193: }
1194:
1195: /**
1196: * Sets a name/value pair in an internal Map that is accessible from the
1197: * Error screen. This is a good way to get debugging information
1198: * when an exception is thrown.
1199: *
1200: * @param name name of the variable
1201: * @param value value of the variable.
1202: */
1203: public void setDebugVariable(String name, Object value) {
1204: this .debugVariables.put(name, value);
1205: }
1206:
1207: /**
1208: * Gets a Map of debug variables.
1209: *
1210: * @return a Map of debug variables.
1211: */
1212: public Map getDebugVariables() {
1213: return this .debugVariables;
1214: }
1215:
1216: // **********************************************
1217: // Implementation of the TurbineRunData interface
1218: // **********************************************
1219:
1220: /**
1221: * Gets the parameter parser without parsing the parameters.
1222: *
1223: * @return the parameter parser.
1224: * @todo Does this method make sense? Pulling the parameter out of
1225: * the run data object before setting a request (which happens
1226: * only in getParameters() leads to the Parameter parser having
1227: * no object and thus the default or even an undefined encoding
1228: * instead of the actual request character encoding).
1229: */
1230: public ParameterParser getParameterParser() {
1231: return parameters;
1232: }
1233:
1234: /**
1235: * Sets the parameter parser.
1236: *
1237: * @param parser a parameter parser.
1238: */
1239: public void setParameterParser(ParameterParser parser) {
1240: parameters = parser;
1241: }
1242:
1243: /**
1244: * Gets the cookie parser without parsing the cookies.
1245: *
1246: * @return the cookie parser.
1247: */
1248: public CookieParser getCookieParser() {
1249: return cookies;
1250: }
1251:
1252: /**
1253: * Sets the cookie parser.
1254: *
1255: * @param parser a cookie parser.
1256: */
1257: public void setCookieParser(CookieParser parser) {
1258: cookies = parser;
1259: }
1260:
1261: /**
1262: * Sets the servlet request.
1263: *
1264: * @param req a request.
1265: */
1266: public void setRequest(HttpServletRequest req) {
1267: this .req = req;
1268: }
1269:
1270: /**
1271: * Sets the servlet response.
1272: *
1273: * @param res a response.
1274: */
1275: public void setResponse(HttpServletResponse res) {
1276: this .res = res;
1277: }
1278:
1279: /**
1280: * Sets the servlet session information.
1281: *
1282: * @param sess a session.
1283: * @deprecated No replacement. This method no longer does anything.
1284: */
1285: public void setSession(HttpSession sess) {
1286: }
1287:
1288: /**
1289: * Sets the servlet configuration used during servlet init.
1290: *
1291: * @param config a configuration.
1292: */
1293: public void setServletConfig(ServletConfig config) {
1294: this .config = config;
1295: if (config == null) {
1296: this .servletContext = null;
1297: } else {
1298: this .servletContext = config.getServletContext();
1299: }
1300: }
1301:
1302: /**
1303: * Sets the server data of the request.
1304: *
1305: * @param serverData server data.
1306: */
1307: public void setServerData(ServerData serverData) {
1308: this .serverData = serverData;
1309: }
1310:
1311: // ********************
1312: // Miscellanous setters
1313: // ********************
1314:
1315: /**
1316: * Sets the print writer.
1317: *
1318: * @param out a print writer.
1319: * @deprecated no replacement planned, response writer will not be cached
1320: */
1321: protected void setOut(PrintWriter out) {
1322: this .out = out;
1323: }
1324:
1325: /**
1326: * Sets the cached server scheme that is stored in the server data.
1327: *
1328: * @param serverScheme a string.
1329: */
1330: protected void setServerScheme(String serverScheme) {
1331: getServerData().setServerScheme(serverScheme);
1332: }
1333:
1334: /**
1335: * Sets the cached server same that is stored in the server data.
1336: *
1337: * @param serverName a string.
1338: */
1339: protected void setServerName(String serverName) {
1340: getServerData().setServerName(serverName);
1341: }
1342:
1343: /**
1344: * Sets the cached server port that is stored in the server data.
1345: *
1346: * @param port an int.
1347: */
1348: protected void setServerPort(int port) {
1349: getServerData().setServerPort(port);
1350: }
1351:
1352: /**
1353: * Sets the cached context path that is stored in the server data.
1354: *
1355: * @param contextPath a string.
1356: */
1357: protected void setContextPath(String contextPath) {
1358: getServerData().setContextPath(contextPath);
1359: }
1360:
1361: /**
1362: * Sets the cached script name that is stored in the server data.
1363: *
1364: * @param scriptName a string.
1365: */
1366: protected void setScriptName(String scriptName) {
1367: getServerData().setScriptName(scriptName);
1368: }
1369: }
|