001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jxpath.servlet;
017:
018: import javax.servlet.ServletContext;
019: import javax.servlet.ServletRequest;
020: import javax.servlet.http.HttpServletRequest;
021: import javax.servlet.http.HttpSession;
022: import javax.servlet.jsp.PageContext;
023: import org.apache.commons.jxpath.JXPathContext;
024: import org.apache.commons.jxpath.JXPathContextFactory;
025: import org.apache.commons.jxpath.JXPathIntrospector;
026:
027: /**
028: * Static methods that allocate and cache JXPathContexts bound to PageContext,
029: * ServletRequest, HttpSession and ServletContext.
030: * <p>
031: * The JXPathContext returned by {@link #getPageContext getPageContext()}
032: * provides access to all scopes via the PageContext.findAttribute()
033: * method. Thus, an expression like "foo" will first look for the attribute
034: * named "foo" in the "page" context, then the "request" context, then
035: * the "session" one and finally in the "application" context.
036: * <p>
037: * If you need to limit the attibute lookup to just one scope, you can use the
038: * pre-definded variables "page", "request", "session" and "application".
039: * For example, the expression "$session/foo" extracts the value of the
040: * session attribute named "foo".
041: * <p>
042: * Following are some implementation details. There is a separate JXPathContext
043: * for each of the four scopes. These contexts are chained according to the
044: * nesting of the scopes. So, the parent of the "page" JXPathContext is a
045: * "request" JXPathContext, whose parent is a "session" JXPathContext (that is
046: * if there is a session), whose parent is an "application" context.
047: * <p>
048: * The XPath context node for each context is the corresponding object:
049: * PageContext, ServletRequest, HttpSession or ServletContext. This feature can
050: * be used by servlets. A servlet can use one of the methods declared by this
051: * class and work with a specific JXPathContext for any scope.
052: * <p>
053: * Since JXPath chains lookups for variables and extension functions, variables
054: * and extension function declared in the outer scopes are also available in
055: * the inner scopes.
056: * <p>
057: * Each of the four context declares exactly one variable, the value of which
058: * is the corresponding object: PageContext, etc.
059: * <p>
060: * The "session" variable will be undefined if there is no session for this
061: * servlet. JXPath does not automatically create sessions.
062: *
063: * @author Dmitri Plotnikov
064: * @version $Revision: 1.6 $ $Date: 2004/05/08 15:10:49 $
065: */
066: public final class JXPathServletContexts {
067:
068: private static JXPathContextFactory factory;
069:
070: static {
071: JXPathIntrospector.registerDynamicClass(PageScopeContext.class,
072: PageScopeContextHandler.class);
073: JXPathIntrospector.registerDynamicClass(PageContext.class,
074: PageContextHandler.class);
075: JXPathIntrospector.registerDynamicClass(ServletContext.class,
076: ServletContextHandler.class);
077: JXPathIntrospector.registerDynamicClass(
078: ServletRequestAndContext.class,
079: ServletRequestHandler.class);
080: JXPathIntrospector.registerDynamicClass(
081: HttpSessionAndServletContext.class,
082: HttpSessionHandler.class);
083: factory = JXPathContextFactory.newInstance();
084: }
085:
086: /**
087: * Returns a JXPathContext bound to the "page" scope. Caches that context
088: * within the PageContext itself.
089: */
090: public static JXPathContext getPageContext(PageContext pageContext) {
091: JXPathContext context = (JXPathContext) pageContext
092: .getAttribute(Constants.JXPATH_CONTEXT);
093: if (context == null) {
094: JXPathContext parentContext = getRequestContext(pageContext
095: .getRequest(), pageContext.getServletContext());
096: context = factory.newContext(parentContext, pageContext);
097: context.setVariables(new KeywordVariables(
098: Constants.PAGE_SCOPE, new PageScopeContext(
099: pageContext)));
100: pageContext.setAttribute(Constants.JXPATH_CONTEXT, context);
101: }
102: return context;
103: }
104:
105: /**
106: * Returns a JXPathContext bound to the "request" scope. Caches that context
107: * within the request itself.
108: */
109: public static JXPathContext getRequestContext(
110: ServletRequest request, ServletContext servletContext) {
111: JXPathContext context = (JXPathContext) request
112: .getAttribute(Constants.JXPATH_CONTEXT);
113: // If we are in an included JSP or Servlet, the request parameter
114: // will represent the included URL, but the JXPathContext we have
115: // just acquired will represent the outer request.
116: if (context != null) {
117: ServletRequestAndContext handle = (ServletRequestAndContext) context
118: .getContextBean();
119: if (handle.getServletRequest() == request) {
120: return context;
121: }
122: }
123:
124: JXPathContext parentContext = null;
125: if (request instanceof HttpServletRequest) {
126: HttpSession session = ((HttpServletRequest) request)
127: .getSession(false);
128: if (session != null) {
129: parentContext = getSessionContext(session,
130: servletContext);
131: } else {
132: parentContext = getApplicationContext(servletContext);
133: }
134: }
135: ServletRequestAndContext handle = new ServletRequestAndContext(
136: request, servletContext);
137: context = factory.newContext(parentContext, handle);
138: context.setVariables(new KeywordVariables(
139: Constants.REQUEST_SCOPE, handle));
140: request.setAttribute(Constants.JXPATH_CONTEXT, context);
141: return context;
142: }
143:
144: /**
145: * Returns a JXPathContext bound to the "session" scope. Caches that context
146: * within the session itself.
147: */
148: public static JXPathContext getSessionContext(HttpSession session,
149: ServletContext servletContext) {
150: JXPathContext context = (JXPathContext) session
151: .getAttribute(Constants.JXPATH_CONTEXT);
152: if (context == null) {
153: JXPathContext parentContext = getApplicationContext(servletContext);
154: HttpSessionAndServletContext handle = new HttpSessionAndServletContext(
155: session, servletContext);
156: context = factory.newContext(parentContext, handle);
157: context.setVariables(new KeywordVariables(
158: Constants.SESSION_SCOPE, handle));
159: session.setAttribute(Constants.JXPATH_CONTEXT, context);
160: }
161: return context;
162: }
163:
164: /**
165: * Returns a JXPathContext bound to the "application" scope. Caches that
166: * context within the servlet context itself.
167: */
168: public static JXPathContext getApplicationContext(
169: ServletContext servletContext) {
170: JXPathContext context = (JXPathContext) servletContext
171: .getAttribute(Constants.JXPATH_CONTEXT);
172: if (context == null) {
173: context = factory.newContext(null, servletContext);
174: context.setVariables(new KeywordVariables(
175: Constants.APPLICATION_SCOPE, servletContext));
176: servletContext.setAttribute(Constants.JXPATH_CONTEXT,
177: context);
178: }
179: return context;
180: }
181: }
|