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