001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.runtime;
019:
020: import java.io.IOException;
021: import java.io.Writer;
022: import java.util.ArrayList;
023: import java.util.Enumeration;
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.Map;
027:
028: import javax.el.ELContext;
029: import javax.servlet.Servlet;
030: import javax.servlet.ServletConfig;
031: import javax.servlet.ServletContext;
032: import javax.servlet.ServletException;
033: import javax.servlet.ServletRequest;
034: import javax.servlet.ServletResponse;
035: import javax.servlet.http.HttpSession;
036: import javax.servlet.jsp.JspContext;
037: import javax.servlet.jsp.JspWriter;
038: import javax.servlet.jsp.PageContext;
039: import javax.servlet.jsp.el.ELException;
040: import javax.servlet.jsp.el.ExpressionEvaluator;
041: import javax.servlet.jsp.el.VariableResolver;
042: import javax.servlet.jsp.tagext.BodyContent;
043: import javax.servlet.jsp.tagext.VariableInfo;
044:
045: import org.apache.jasper.compiler.Localizer;
046: import org.apache.jasper.util.Enumerator;
047:
048: /**
049: * Implementation of a JSP Context Wrapper.
050: *
051: * The JSP Context Wrapper is a JspContext created and maintained by a tag
052: * handler implementation. It wraps the Invoking JSP Context, that is, the
053: * JspContext instance passed to the tag handler by the invoking page via
054: * setJspContext().
055: *
056: * @author Kin-man Chung
057: * @author Jan Luehe
058: * @author Jacob Hookom
059: */
060: public class JspContextWrapper extends PageContext implements
061: VariableResolver {
062:
063: // Invoking JSP context
064: private PageContext invokingJspCtxt;
065:
066: private transient HashMap<String, Object> pageAttributes;
067:
068: // ArrayList of NESTED scripting variables
069: private ArrayList nestedVars;
070:
071: // ArrayList of AT_BEGIN scripting variables
072: private ArrayList atBeginVars;
073:
074: // ArrayList of AT_END scripting variables
075: private ArrayList atEndVars;
076:
077: private Map aliases;
078:
079: private HashMap<String, Object> originalNestedVars;
080:
081: public JspContextWrapper(JspContext jspContext,
082: ArrayList nestedVars, ArrayList atBeginVars,
083: ArrayList atEndVars, Map aliases) {
084: this .invokingJspCtxt = (PageContext) jspContext;
085: this .nestedVars = nestedVars;
086: this .atBeginVars = atBeginVars;
087: this .atEndVars = atEndVars;
088: this .pageAttributes = new HashMap<String, Object>(16);
089: this .aliases = aliases;
090:
091: if (nestedVars != null) {
092: this .originalNestedVars = new HashMap<String, Object>(
093: nestedVars.size());
094: }
095: syncBeginTagFile();
096: }
097:
098: public void initialize(Servlet servlet, ServletRequest request,
099: ServletResponse response, String errorPageURL,
100: boolean needsSession, int bufferSize, boolean autoFlush)
101: throws IOException, IllegalStateException,
102: IllegalArgumentException {
103: }
104:
105: public Object getAttribute(String name) {
106:
107: if (name == null) {
108: throw new NullPointerException(Localizer
109: .getMessage("jsp.error.attribute.null_name"));
110: }
111:
112: return pageAttributes.get(name);
113: }
114:
115: public Object getAttribute(String name, int scope) {
116:
117: if (name == null) {
118: throw new NullPointerException(Localizer
119: .getMessage("jsp.error.attribute.null_name"));
120: }
121:
122: if (scope == PAGE_SCOPE) {
123: return pageAttributes.get(name);
124: }
125:
126: return invokingJspCtxt.getAttribute(name, scope);
127: }
128:
129: public void setAttribute(String name, Object value) {
130:
131: if (name == null) {
132: throw new NullPointerException(Localizer
133: .getMessage("jsp.error.attribute.null_name"));
134: }
135:
136: if (value != null) {
137: pageAttributes.put(name, value);
138: } else {
139: removeAttribute(name, PAGE_SCOPE);
140: }
141: }
142:
143: public void setAttribute(String name, Object value, int scope) {
144:
145: if (name == null) {
146: throw new NullPointerException(Localizer
147: .getMessage("jsp.error.attribute.null_name"));
148: }
149:
150: if (scope == PAGE_SCOPE) {
151: if (value != null) {
152: pageAttributes.put(name, value);
153: } else {
154: removeAttribute(name, PAGE_SCOPE);
155: }
156: } else {
157: invokingJspCtxt.setAttribute(name, value, scope);
158: }
159: }
160:
161: public Object findAttribute(String name) {
162:
163: if (name == null) {
164: throw new NullPointerException(Localizer
165: .getMessage("jsp.error.attribute.null_name"));
166: }
167:
168: Object o = pageAttributes.get(name);
169: if (o == null) {
170: o = invokingJspCtxt.getAttribute(name, REQUEST_SCOPE);
171: if (o == null) {
172: if (getSession() != null) {
173: o = invokingJspCtxt.getAttribute(name,
174: SESSION_SCOPE);
175: }
176: if (o == null) {
177: o = invokingJspCtxt.getAttribute(name,
178: APPLICATION_SCOPE);
179: }
180: }
181: }
182:
183: return o;
184: }
185:
186: public void removeAttribute(String name) {
187:
188: if (name == null) {
189: throw new NullPointerException(Localizer
190: .getMessage("jsp.error.attribute.null_name"));
191: }
192:
193: pageAttributes.remove(name);
194: invokingJspCtxt.removeAttribute(name, REQUEST_SCOPE);
195: if (getSession() != null) {
196: invokingJspCtxt.removeAttribute(name, SESSION_SCOPE);
197: }
198: invokingJspCtxt.removeAttribute(name, APPLICATION_SCOPE);
199: }
200:
201: public void removeAttribute(String name, int scope) {
202:
203: if (name == null) {
204: throw new NullPointerException(Localizer
205: .getMessage("jsp.error.attribute.null_name"));
206: }
207:
208: if (scope == PAGE_SCOPE) {
209: pageAttributes.remove(name);
210: } else {
211: invokingJspCtxt.removeAttribute(name, scope);
212: }
213: }
214:
215: public int getAttributesScope(String name) {
216:
217: if (name == null) {
218: throw new NullPointerException(Localizer
219: .getMessage("jsp.error.attribute.null_name"));
220: }
221:
222: if (pageAttributes.get(name) != null) {
223: return PAGE_SCOPE;
224: } else {
225: return invokingJspCtxt.getAttributesScope(name);
226: }
227: }
228:
229: public Enumeration<String> getAttributeNamesInScope(int scope) {
230: if (scope == PAGE_SCOPE) {
231: return new Enumerator(pageAttributes.keySet().iterator());
232: }
233:
234: return invokingJspCtxt.getAttributeNamesInScope(scope);
235: }
236:
237: public void release() {
238: invokingJspCtxt.release();
239: }
240:
241: public JspWriter getOut() {
242: return invokingJspCtxt.getOut();
243: }
244:
245: public HttpSession getSession() {
246: return invokingJspCtxt.getSession();
247: }
248:
249: public Object getPage() {
250: return invokingJspCtxt.getPage();
251: }
252:
253: public ServletRequest getRequest() {
254: return invokingJspCtxt.getRequest();
255: }
256:
257: public ServletResponse getResponse() {
258: return invokingJspCtxt.getResponse();
259: }
260:
261: public Exception getException() {
262: return invokingJspCtxt.getException();
263: }
264:
265: public ServletConfig getServletConfig() {
266: return invokingJspCtxt.getServletConfig();
267: }
268:
269: public ServletContext getServletContext() {
270: return invokingJspCtxt.getServletContext();
271: }
272:
273: public void forward(String relativeUrlPath)
274: throws ServletException, IOException {
275: invokingJspCtxt.forward(relativeUrlPath);
276: }
277:
278: public void include(String relativeUrlPath)
279: throws ServletException, IOException {
280: invokingJspCtxt.include(relativeUrlPath);
281: }
282:
283: public void include(String relativeUrlPath, boolean flush)
284: throws ServletException, IOException {
285: include(relativeUrlPath, false); // XXX
286: }
287:
288: public VariableResolver getVariableResolver() {
289: return this ;
290: }
291:
292: public BodyContent pushBody() {
293: return invokingJspCtxt.pushBody();
294: }
295:
296: public JspWriter pushBody(Writer writer) {
297: return invokingJspCtxt.pushBody(writer);
298: }
299:
300: public JspWriter popBody() {
301: return invokingJspCtxt.popBody();
302: }
303:
304: public ExpressionEvaluator getExpressionEvaluator() {
305: return invokingJspCtxt.getExpressionEvaluator();
306: }
307:
308: public void handlePageException(Exception ex) throws IOException,
309: ServletException {
310: // Should never be called since handleException() called with a
311: // Throwable in the generated servlet.
312: handlePageException((Throwable) ex);
313: }
314:
315: public void handlePageException(Throwable t) throws IOException,
316: ServletException {
317: invokingJspCtxt.handlePageException(t);
318: }
319:
320: /**
321: * VariableResolver interface
322: */
323: public Object resolveVariable(String pName) throws ELException {
324: ELContext ctx = this .getELContext();
325: return ctx.getELResolver().getValue(ctx, null, pName);
326: }
327:
328: /**
329: * Synchronize variables at begin of tag file
330: */
331: public void syncBeginTagFile() {
332: saveNestedVariables();
333: }
334:
335: /**
336: * Synchronize variables before fragment invokation
337: */
338: public void syncBeforeInvoke() {
339: copyTagToPageScope(VariableInfo.NESTED);
340: copyTagToPageScope(VariableInfo.AT_BEGIN);
341: }
342:
343: /**
344: * Synchronize variables at end of tag file
345: */
346: public void syncEndTagFile() {
347: copyTagToPageScope(VariableInfo.AT_BEGIN);
348: copyTagToPageScope(VariableInfo.AT_END);
349: restoreNestedVariables();
350: }
351:
352: /**
353: * Copies the variables of the given scope from the virtual page scope of
354: * this JSP context wrapper to the page scope of the invoking JSP context.
355: *
356: * @param scope
357: * variable scope (one of NESTED, AT_BEGIN, or AT_END)
358: */
359: private void copyTagToPageScope(int scope) {
360: Iterator iter = null;
361:
362: switch (scope) {
363: case VariableInfo.NESTED:
364: if (nestedVars != null) {
365: iter = nestedVars.iterator();
366: }
367: break;
368: case VariableInfo.AT_BEGIN:
369: if (atBeginVars != null) {
370: iter = atBeginVars.iterator();
371: }
372: break;
373: case VariableInfo.AT_END:
374: if (atEndVars != null) {
375: iter = atEndVars.iterator();
376: }
377: break;
378: }
379:
380: while ((iter != null) && iter.hasNext()) {
381: String varName = (String) iter.next();
382: Object obj = getAttribute(varName);
383: varName = findAlias(varName);
384: if (obj != null) {
385: invokingJspCtxt.setAttribute(varName, obj);
386: } else {
387: invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE);
388: }
389: }
390: }
391:
392: /**
393: * Saves the values of any NESTED variables that are present in the invoking
394: * JSP context, so they can later be restored.
395: */
396: private void saveNestedVariables() {
397: if (nestedVars != null) {
398: Iterator iter = nestedVars.iterator();
399: while (iter.hasNext()) {
400: String varName = (String) iter.next();
401: varName = findAlias(varName);
402: Object obj = invokingJspCtxt.getAttribute(varName);
403: if (obj != null) {
404: originalNestedVars.put(varName, obj);
405: }
406: }
407: }
408: }
409:
410: /**
411: * Restores the values of any NESTED variables in the invoking JSP context.
412: */
413: private void restoreNestedVariables() {
414: if (nestedVars != null) {
415: Iterator iter = nestedVars.iterator();
416: while (iter.hasNext()) {
417: String varName = (String) iter.next();
418: varName = findAlias(varName);
419: Object obj = originalNestedVars.get(varName);
420: if (obj != null) {
421: invokingJspCtxt.setAttribute(varName, obj);
422: } else {
423: invokingJspCtxt
424: .removeAttribute(varName, PAGE_SCOPE);
425: }
426: }
427: }
428: }
429:
430: /**
431: * Checks to see if the given variable name is used as an alias, and if so,
432: * returns the variable name for which it is used as an alias.
433: *
434: * @param varName
435: * The variable name to check
436: * @return The variable name for which varName is used as an alias, or
437: * varName if it is not being used as an alias
438: */
439: private String findAlias(String varName) {
440:
441: if (aliases == null)
442: return varName;
443:
444: String alias = (String) aliases.get(varName);
445: if (alias == null) {
446: return varName;
447: }
448: return alias;
449: }
450:
451: //private ELContextImpl elContext;
452:
453: public ELContext getELContext() {
454: // instead decorate!!!
455:
456: return this .invokingJspCtxt.getELContext();
457:
458: /*
459: if (this.elContext != null) {
460: JspFactory jspFact = JspFactory.getDefaultFactory();
461: ServletContext servletContext = this.getServletContext();
462: JspApplicationContextImpl jspCtx = (JspApplicationContextImpl) jspFact
463: .getJspApplicationContext(servletContext);
464: this.elContext = jspCtx.createELContext(this);
465: }
466: return this.elContext;
467: */
468: }
469: }
|