1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.web.servlet.view;
  17. import java.util.Iterator;
  18. import java.util.Map;
  19. import javax.servlet.RequestDispatcher;
  20. import javax.servlet.ServletException;
  21. import javax.servlet.http.HttpServletRequest;
  22. import javax.servlet.http.HttpServletResponse;
  23. import org.springframework.web.util.UrlPathHelper;
  24. /**
  25. * Wrapper for a JSP or other resource within the same web application.
  26. * Exposes model objects as request attributes and forwards the request to
  27. * the specified resource URL using a RequestDispatcher. Will fall back to
  28. * an include if already in an included request.
  29. *
  30. * <p>A URL for this view is supposed to specify a resource within the web
  31. * application, i.e. suitable for RequestDispatcher's forward/include methods.
  32. *
  33. * @author Rod Johnson
  34. * @author Juergen Hoeller
  35. * @version $Id: InternalResourceView.java,v 1.12 2004/03/24 11:38:48 jhoeller Exp $
  36. * @see javax.servlet.RequestDispatcher#forward
  37. * @see javax.servlet.RequestDispatcher#include
  38. */
  39. public class InternalResourceView extends AbstractUrlBasedView {
  40. /**
  41. * Constructor for use as a bean.
  42. */
  43. public InternalResourceView() {
  44. }
  45. /**
  46. * Create a new InternalResourceView with the given URL.
  47. * @param url the URL to forward to
  48. */
  49. public InternalResourceView(String url) {
  50. setUrl(url);
  51. }
  52. /**
  53. * Render the internal resource given the specified model.
  54. * This includes setting the model as request attributes.
  55. */
  56. protected void renderMergedOutputModel(Map model, HttpServletRequest request,
  57. HttpServletResponse response) throws Exception {
  58. // expose the model object as request attributes
  59. exposeModelAsRequestAttributes(model, request);
  60. // determine the path for the request dispatcher
  61. String dispatcherPath = prepareForRendering(request, response);
  62. // forward to the resource (typically a JSP)
  63. // Note: The JSP is supposed to determine the content type itself.
  64. RequestDispatcher rd = request.getRequestDispatcher(dispatcherPath);
  65. if (rd == null) {
  66. throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
  67. "]: check that this file exists within your WAR");
  68. }
  69. // if already included, include again, else forward
  70. if (request.getAttribute(UrlPathHelper.INCLUDE_URI_REQUEST_ATTRIBUTE) != null) {
  71. rd.include(request, response);
  72. logger.debug("Included resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
  73. }
  74. else {
  75. rd.forward(request, response);
  76. logger.debug("Forwarded to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
  77. }
  78. }
  79. /**
  80. * Expose the model objects in the given map as request attributes.
  81. * Names will be taken from the map.
  82. * This method is suitable for all resources reachable by RequestDispatcher.
  83. * @param model Map of model objects to expose
  84. * @param request current HTTP request
  85. */
  86. protected void exposeModelAsRequestAttributes(Map model, HttpServletRequest request) throws ServletException {
  87. if (model != null) {
  88. Iterator it = model.keySet().iterator();
  89. while (it.hasNext()) {
  90. Object key = it.next();
  91. if (!(key instanceof String)) {
  92. throw new ServletException("Invalid key [" + key + "] in model Map - only Strings allowed as model keys");
  93. }
  94. String modelName = (String) key;
  95. Object modelValue = model.get(modelName);
  96. if (modelValue != null) {
  97. request.setAttribute(modelName, modelValue);
  98. if (logger.isDebugEnabled()) {
  99. logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
  100. "] to request in InternalResourceView '" + getBeanName() + "' ");
  101. }
  102. }
  103. }
  104. }
  105. else {
  106. logger.debug("Model is null. Nothing to expose to request.");
  107. }
  108. }
  109. /**
  110. * Prepare for rendering, and determine the request dispatcher path
  111. * to forward to respectively to include.
  112. * <p>This implementation simply returns the configured URL.
  113. * Subclasses can override this to determine a resource to render,
  114. * typically interpreting the URL in a different manner.
  115. * @param request current HTTP request
  116. * @param response current HTTP response
  117. * @return the request dispatcher path to use
  118. * @throws Exception if preparations failed
  119. * @see #getUrl
  120. * @see org.springframework.web.servlet.view.tiles.TilesView#prepareForRendering
  121. */
  122. protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response)
  123. throws Exception {
  124. return getUrl();
  125. }
  126. }