Java tutorial
/* * Copyright 2004-2005 Graeme Rocher * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.grails.gsp.jsp; import groovy.lang.Binding; import java.io.IOException; import java.io.Writer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import javax.el.ELContext; import javax.servlet.GenericServlet; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.jsp.*; import javax.servlet.jsp.el.ELException; import javax.servlet.jsp.el.ExpressionEvaluator; import javax.servlet.jsp.el.VariableResolver; import javax.servlet.jsp.tagext.BodyContent; import org.grails.gsp.GroovyPage; import org.grails.web.servlet.mvc.GrailsWebRequest; import org.springframework.util.Assert; import org.springframework.web.context.request.RequestContextHolder; /** * A JSP PageContext implementation for use with GSP. * * @author Graeme Rocher * @since 1.1 */ public class GroovyPagesPageContext extends PageContext { private static final Enumeration EMPTY_ENUMERATION = new Enumeration() { @Override public boolean hasMoreElements() { return false; } @Override public Object nextElement() { return new NoSuchElementException(); } }; private ServletContext servletContext; private Servlet servlet; private HttpServletRequest request; private HttpServletResponse response; private ServletConfig servletconfig; private Binding pageScope; private GrailsWebRequest webRequest; private JspWriter jspOut; private Deque outStack = new ArrayDeque(); @SuppressWarnings("rawtypes") private List tags = new ArrayList(); private HttpSession session; public GroovyPagesPageContext(Servlet pagesServlet, Binding pageScope) { Assert.notNull(pagesServlet, "GroovyPagesPageContext class requires a reference to the GSP servlet"); webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes(); servletContext = webRequest.getServletContext(); request = webRequest.getCurrentRequest(); response = webRequest.getCurrentResponse(); servlet = pagesServlet; servletconfig = pagesServlet.getServletConfig(); this.pageScope = pageScope; session = request.getSession(false); // setup initial writer pushWriter(new JspWriterDelegate(webRequest.getOut())); // Register page attributes as per JSP spec setAttribute(REQUEST, request); setAttribute(RESPONSE, response); if (session != null) { setAttribute(SESSION, session); } setAttribute(PAGE, servlet); setAttribute(CONFIG, servlet.getServletConfig()); setAttribute(PAGECONTEXT, this); setAttribute(APPLICATION, servletContext); } void popWriter() { outStack.pop(); jspOut = (JspWriter) outStack.peek(); setCurrentOut(); } void pushWriter(JspWriter out) { outStack.push(out); jspOut = out; setCurrentOut(); } private void setCurrentOut() { setAttribute(OUT, jspOut); setAttribute(GroovyPage.OUT, jspOut); webRequest.setOut(jspOut); } Object peekTopTag(Class<?> tagClass) { for (ListIterator<?> iter = tags.listIterator(tags.size()); iter.hasPrevious();) { Object tag = iter.previous(); if (tagClass.isInstance(tag)) { return tag; } } return null; } void popTopTag() { tags.remove(tags.size() - 1); } @SuppressWarnings("unchecked") void pushTopTag(Object tag) { tags.add(tag); } @Override public BodyContent pushBody() { BodyContent bc = new BodyContentImpl(getOut(), true); pushWriter(bc); return bc; } @Override public JspWriter popBody() { popWriter(); return (JspWriter) getAttribute(OUT); } @SuppressWarnings("serial") public GroovyPagesPageContext(Binding pageScope) { this(new GenericServlet() { @Override public ServletConfig getServletConfig() { return this; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { // do nothing; } }, pageScope != null ? pageScope : new Binding()); } public GroovyPagesPageContext() { this(new Binding()); } @Override public void initialize(Servlet s, ServletRequest servletRequest, ServletResponse servletResponse, String errorPageURL, boolean needSession, int bufferSize, boolean autoFlush) { // do nothing, not constructed for container } @Override public void release() { // do nothing, not released by container } @Override public HttpSession getSession() { return request.getSession(false); } @Override public Object getPage() { return servlet; } @Override public ServletRequest getRequest() { return request; } @Override public ServletResponse getResponse() { return response; } @Override public Exception getException() { throw new UnsupportedOperationException(); } @Override public ServletConfig getServletConfig() { return servletconfig; } @Override public ServletContext getServletContext() { return servletContext; } @Override public void forward(String url) throws ServletException, IOException { request.getRequestDispatcher(url).forward(request, response); } @Override public void include(String url) throws ServletException, IOException { include(url, false); } @Override public void include(String url, boolean flush) throws ServletException, IOException { request.getRequestDispatcher(url).include(request, response); } @Override public void handlePageException(Exception e) throws ServletException, IOException { throw new UnsupportedOperationException(); } @Override public void handlePageException(Throwable throwable) throws ServletException, IOException { throw new UnsupportedOperationException(); } @Override public void setAttribute(String name, Object value) { Assert.notNull(name, "Attribute name cannot be null"); pageScope.setVariable(name, value); } @Override public void setAttribute(String name, Object value, int scope) { Assert.notNull(name, "Attribute name cannot be null"); switch (scope) { case PAGE_SCOPE: setAttribute(name, value); break; case REQUEST_SCOPE: request.setAttribute(name, value); break; case SESSION_SCOPE: request.getSession(true).setAttribute(name, value); break; case APPLICATION_SCOPE: servletContext.setAttribute(name, value); break; default: setAttribute(name, value); } } @Override public Object getAttribute(String name) { Assert.notNull(name, "Attribute name cannot be null"); if (pageScope.getVariables().containsKey(name)) { return pageScope.getVariable(name); } return null; } @Override public Object getAttribute(String name, int scope) { Assert.notNull(name, "Attribute name cannot be null"); switch (scope) { case PAGE_SCOPE: return getAttribute(name); case REQUEST_SCOPE: return request.getAttribute(name); case SESSION_SCOPE: return request.getSession(true).getAttribute(name); case APPLICATION_SCOPE: return servletContext.getAttribute(name); default: return getAttribute(name); } } @Override public Object findAttribute(String name) { Assert.notNull(name, "Attribute name cannot be null"); int scope = getAttributesScope(name); if (scope > 0) { return getAttribute(name, scope); } return null; } @Override public void removeAttribute(String name) { Assert.notNull(name, "Attribute name cannot be null"); pageScope.getVariables().remove(name); } @Override public void removeAttribute(String name, int scope) { Assert.notNull(name, "Attribute name cannot be null"); switch (scope) { case PAGE_SCOPE: removeAttribute(name); break; case REQUEST_SCOPE: request.removeAttribute(name); break; case SESSION_SCOPE: HttpSession httpSession = request.getSession(false); if (httpSession != null) { httpSession.removeAttribute(name); } break; case APPLICATION_SCOPE: servletContext.removeAttribute(name); break; default: removeAttribute(name); } } @Override public int getAttributesScope(String name) { Assert.notNull(name, "Attribute name cannot be null"); if (pageScope.getVariables().containsKey(name)) { return PAGE_SCOPE; } if (request.getAttribute(name) != null) { return REQUEST_SCOPE; } HttpSession httpSession = request.getSession(false); if (httpSession != null && httpSession.getAttribute(name) != null) { return SESSION_SCOPE; } if (servletContext.getAttribute(name) != null) { return APPLICATION_SCOPE; } return 0; } @SuppressWarnings("rawtypes") @Override public Enumeration getAttributeNamesInScope(int scope) { switch (scope) { case PAGE_SCOPE: final Iterator i = pageScope.getVariables().keySet().iterator(); return new Enumeration() { @Override public boolean hasMoreElements() { return i.hasNext(); } @Override public Object nextElement() { return i.next(); } }; case REQUEST_SCOPE: return request.getAttributeNames(); case SESSION_SCOPE: HttpSession httpSession = request.getSession(false); if (httpSession != null) { return httpSession.getAttributeNames(); } else { return EMPTY_ENUMERATION; } case APPLICATION_SCOPE: return servletContext.getAttributeNames(); } return EMPTY_ENUMERATION; } @Override public JspWriter getOut() { Writer out = webRequest.getOut(); if (out instanceof JspWriter) { return (JspWriter) out; } out = new JspWriterDelegate(out); webRequest.setOut(out); return (JspWriter) out; } @Override public ExpressionEvaluator getExpressionEvaluator() { try { Class<?> type = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } }).loadClass("org.apache.commons.el.ExpressionEvaluatorImpl"); return (ExpressionEvaluator) type.newInstance(); } catch (Exception e) { throw new UnsupportedOperationException("In order for the getExpressionEvaluator() " + "method to work, you must have downloaded the apache commons-el jar and " + "made it available in the classpath."); } } @Override public VariableResolver getVariableResolver() { final PageContext ctx = this; return new VariableResolver() { public Object resolveVariable(String name) throws ELException { return ctx.findAttribute(name); } }; } static { if (JspFactory.getDefaultFactory() == null) { JspFactory.setDefaultFactory(new GroovyPagesJspFactory()); } } private ELContext elContext; public ELContext getELContext() { if (elContext == null) { JspApplicationContext jspContext = JspFactory.getDefaultFactory() .getJspApplicationContext(getServletContext()); if (jspContext instanceof GroovyPagesJspApplicationContext) { elContext = ((GroovyPagesJspApplicationContext) jspContext).createELContext(this); elContext.putContext(JspContext.class, this); } else { throw new IllegalStateException( "Unable to create ELContext for a JspApplicationContext. It must be an instance of [GroovyPagesJspApplicationContext] do not override JspFactory.setDefaultFactory()!"); } } return elContext; } }