/**
 * Encapsulates a Grails request. An instance of this class is bound to the current thread using
 * Spring's RequestContextHolder which can later be retrieved using:
 *
 * <p>def webRequest = RequestContextHolder.currentRequestAttributes()
 *
 * @author Graeme Rocher
 * @since 3.0
 */
public class GrailsWebRequest extends DispatcherServletWebRequest {

  private static final String REDIRECT_CALLED = GrailsApplicationAttributes.REDIRECT_ISSUED;

  private static final Class<? extends GrailsApplicationAttributes>
      grailsApplicationAttributesClass =
          GrailsFactoriesLoader.loadFactoryClasses(
                  GrailsApplicationAttributes.class, GrailsWebRequest.class.getClassLoader())
              .get(0);
  private static final Constructor<? extends GrailsApplicationAttributes>
      grailsApplicationAttributesConstructor =
          ClassUtils.getConstructorIfAvailable(
              grailsApplicationAttributesClass, ServletContext.class);
  private GrailsApplicationAttributes attributes;
  private GrailsParameterMap params;
  private GrailsParameterMap originalParams;
  private GrailsHttpSession session;
  private boolean renderView = true;
  private boolean skipFilteringCodec = false;
  private Encoder filteringEncoder;
  public static final String ID_PARAMETER = "id";
  private final List<ParameterCreationListener> parameterCreationListeners =
      new ArrayList<ParameterCreationListener>();
  private final UrlPathHelper urlHelper = new UrlPathHelper();
  private ApplicationContext applicationContext;
  private String baseUrl;
  private HttpServletResponse wrappedResponse;

  private EncodingStateRegistry encodingStateRegistry;
  private HttpServletRequest multipartRequest;

  public GrailsWebRequest(
      HttpServletRequest request,
      HttpServletResponse response,
      GrailsApplicationAttributes attributes) {
    super(request, response);
    this.attributes = attributes;
    this.applicationContext = attributes.getApplicationContext();
    inheritEncodingStateRegistry();
  }

  public GrailsWebRequest(
      HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {
    super(request, response);
    try {
      attributes = grailsApplicationAttributesConstructor.newInstance(servletContext);
      this.applicationContext = attributes.getApplicationContext();
    } catch (Exception e) {
      ReflectionUtils.rethrowRuntimeException(e);
    }
    inheritEncodingStateRegistry();
  }

  public GrailsWebRequest(
      HttpServletRequest request,
      HttpServletResponse response,
      ServletContext servletContext,
      ApplicationContext applicationContext) {
    this(request, response, servletContext);
    this.applicationContext = applicationContext;
  }

  /**
   * Holds a reference to the {@link org.springframework.web.multipart.MultipartRequest}
   *
   * @param multipartRequest The multipart request
   */
  public void setMultipartRequest(HttpServletRequest multipartRequest) {
    this.multipartRequest = multipartRequest;
  }

  private void inheritEncodingStateRegistry() {
    GrailsWebRequest parentRequest = GrailsWebRequest.lookup(getRequest());
    if (parentRequest != null) {
      this.encodingStateRegistry = parentRequest.getEncodingStateRegistry();
    }
  }

  /**
   * Overriden to return the GrailsParameterMap instance,
   *
   * @return An instance of GrailsParameterMap
   */
  @Override
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Map getParameterMap() {
    if (params == null) {
      resetParams();
    }
    return params;
  }

  @Override
  public void requestCompleted() {
    super.requestCompleted();
    DeferredBindingActions.clear();
  }

  /** @return the out */
  public Writer getOut() {
    Writer out = attributes.getOut(getCurrentRequest());
    if (out == null) {
      try {
        return getCurrentResponse().getWriter();
      } catch (IOException e) {
        throw new ControllerExecutionException(
            "Error retrieving response writer: " + e.getMessage(), e);
      }
    }
    return out;
  }

  /**
   * Whether the web request is still active
   *
   * @return true if it is
   */
  public boolean isActive() {
    return super.isRequestActive();
  }

  /** @param out the out to set */
  public void setOut(Writer out) {
    attributes.setOut(getCurrentRequest(), out);
  }

  /** @return The ServletContext instance */
  public ServletContext getServletContext() {
    return attributes.getServletContext();
  }

  /**
   * Returns the context path of the request.
   *
   * @return the path
   */
  @Override
  public String getContextPath() {
    final HttpServletRequest request = getCurrentRequest();
    String appUri = (String) request.getAttribute(GrailsApplicationAttributes.APP_URI_ATTRIBUTE);
    if (appUri == null) {
      appUri = urlHelper.getContextPath(request);
    }
    return appUri;
  }

  /** @return The FlashScope instance for the current request */
  public FlashScope getFlashScope() {
    return attributes.getFlashScope(getRequest());
  }

  /** @return The currently executing request */
  public HttpServletRequest getCurrentRequest() {
    if (multipartRequest != null) {
      return multipartRequest;
    } else {
      return getRequest();
    }
  }

  public HttpServletResponse getCurrentResponse() {
    if (wrappedResponse != null) {
      return wrappedResponse;
    } else {
      return getResponse();
    }
  }

  public HttpServletResponse getWrappedResponse() {
    return wrappedResponse;
  }

  public void setWrappedResponse(HttpServletResponse wrappedResponse) {
    this.wrappedResponse = wrappedResponse;
  }

  /** @return The Grails params object */
  public GrailsParameterMap getParams() {
    if (params == null) {
      resetParams();
    }
    return params;
  }

  /** Reset params by re-reading & initializing parameters from request */
  public void resetParams() {
    if (originalParams == null) {
      originalParams = new GrailsParameterMap(getCurrentRequest());
    }
    params = (GrailsParameterMap) originalParams.clone();
  }

  @SuppressWarnings("rawtypes")
  public void addParametersFrom(Map previousParams) {
    if (previousParams instanceof GrailsParameterMap) {
      getParams().addParametersFrom((GrailsParameterMap) previousParams);
    } else {
      for (Object key : previousParams.keySet()) {
        String name = String.valueOf(key);
        getParams().put(name, previousParams.get(key));
      }
    }
  }

  /** Informs any parameter creation listeners. */
  public void informParameterCreationListeners() {
    for (ParameterCreationListener parameterCreationListener : parameterCreationListeners) {
      parameterCreationListener.paramsCreated(getParams());
    }
  }

  /** @return The Grails session object */
  public GrailsHttpSession getSession() {
    if (session == null) {
      session = new GrailsHttpSession(getCurrentRequest());
    }

    return session;
  }

  /** @return The GrailsApplicationAttributes instance */
  public GrailsApplicationAttributes getAttributes() {
    return attributes;
  }

  public void setActionName(String actionName) {
    getCurrentRequest().setAttribute(GrailsApplicationAttributes.ACTION_NAME_ATTRIBUTE, actionName);
  }

  public void setControllerName(String controllerName) {
    getCurrentRequest()
        .setAttribute(GrailsApplicationAttributes.CONTROLLER_NAME_ATTRIBUTE, controllerName);
  }

  public void setControllerNamespace(String controllerNamespace) {
    getCurrentRequest()
        .setAttribute(
            GrailsApplicationAttributes.CONTROLLER_NAMESPACE_ATTRIBUTE, controllerNamespace);
  }

  /** @return the actionName */
  public String getActionName() {
    return (String)
        getCurrentRequest().getAttribute(GrailsApplicationAttributes.ACTION_NAME_ATTRIBUTE);
  }

  /** @return the controllerName */
  public String getControllerName() {
    return (String)
        getCurrentRequest().getAttribute(GrailsApplicationAttributes.CONTROLLER_NAME_ATTRIBUTE);
  }

  /** @return the controllerClass */
  public GrailsControllerClass getControllerClass() {
    HttpServletRequest currentRequest = getCurrentRequest();
    GrailsControllerClass controllerClass =
        (GrailsControllerClass)
            currentRequest.getAttribute(GrailsApplicationAttributes.GRAILS_CONTROLLER_CLASS);
    if (controllerClass == null) {
      Object controllerNameObject =
          currentRequest.getAttribute(GrailsApplicationAttributes.CONTROLLER_NAME_ATTRIBUTE);
      if (controllerNameObject != null) {
        controllerClass =
            (GrailsControllerClass)
                getAttributes()
                    .getGrailsApplication()
                    .getArtefactByLogicalPropertyName(
                        ControllerArtefactHandler.TYPE, controllerNameObject.toString());
        if (controllerClass != null) {
          currentRequest.setAttribute(
              GrailsApplicationAttributes.GRAILS_CONTROLLER_CLASS, controllerClass);
        }
      }
    }
    return controllerClass;
  }

  /** @return the controllerNamespace */
  public String getControllerNamespace() {
    return (String)
        getCurrentRequest()
            .getAttribute(GrailsApplicationAttributes.CONTROLLER_NAMESPACE_ATTRIBUTE);
  }

  public void setRenderView(boolean renderView) {
    this.renderView = renderView;
  }

  /** @return true if the view for this GrailsWebRequest should be rendered */
  public boolean isRenderView() {
    final HttpServletRequest currentRequest = getCurrentRequest();
    HttpServletResponse currentResponse = getCurrentResponse();
    return renderView
        && !currentResponse.isCommitted()
        && currentResponse.getStatus() < 300
        && currentRequest.getAttribute(REDIRECT_CALLED) == null;
  }

  public String getId() {
    Object id = getParams().get(ID_PARAMETER);
    return id == null ? null : id.toString();
  }

  /**
   * Returns true if the current executing request is a flow request
   *
   * @return true if it is a flow request
   */
  public boolean isFlowRequest() {
    GrailsApplication application = getAttributes().getGrailsApplication();
    Object controllerClassObject = getControllerClass();
    GrailsControllerClass controllerClass = null;
    if (controllerClassObject instanceof GrailsControllerClass) {
      controllerClass = (GrailsControllerClass) controllerClassObject;
    }

    if (controllerClass == null) return false;

    String actionName = getActionName();
    if (actionName == null) actionName = controllerClass.getDefaultAction();
    if (actionName == null) return false;

    return false;
  }

  public void addParameterListener(ParameterCreationListener creationListener) {
    parameterCreationListeners.add(creationListener);
  }

  /**
   * Obtains the ApplicationContext object.
   *
   * @return The ApplicationContext
   */
  public ApplicationContext getApplicationContext() {
    return applicationContext == null
        ? getAttributes().getApplicationContext()
        : applicationContext;
  }

  /**
   * Obtains the PropertyEditorRegistry instance.
   *
   * @return The PropertyEditorRegistry
   */
  public PropertyEditorRegistry getPropertyEditorRegistry() {
    final HttpServletRequest servletRequest = getCurrentRequest();
    PropertyEditorRegistry registry =
        (PropertyEditorRegistry)
            servletRequest.getAttribute(GrailsApplicationAttributes.PROPERTY_REGISTRY);
    if (registry == null) {
      registry = new PropertyEditorRegistrySupport();
      PropertyEditorRegistryUtils.registerCustomEditors(
          this, registry, RequestContextUtils.getLocale(servletRequest));
      servletRequest.setAttribute(GrailsApplicationAttributes.PROPERTY_REGISTRY, registry);
    }
    return registry;
  }

  /**
   * Looks up the GrailsWebRequest from the current request.
   *
   * @param request The current request
   * @return The GrailsWebRequest
   */
  public static GrailsWebRequest lookup(HttpServletRequest request) {
    GrailsWebRequest webRequest =
        (GrailsWebRequest) request.getAttribute(GrailsApplicationAttributes.WEB_REQUEST);
    return webRequest == null ? lookup() : webRequest;
  }

  /**
   * Looks up the current Grails WebRequest instance
   *
   * @return The GrailsWebRequest instance
   */
  public static GrailsWebRequest lookup() {
    GrailsWebRequest webRequest = null;
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    if (requestAttributes instanceof GrailsWebRequest) {
      webRequest = (GrailsWebRequest) requestAttributes;
    }
    return webRequest;
  }

  /**
   * Sets the id of the request.
   *
   * @param id The id
   */
  public void setId(Object id) {
    getParams().put(GrailsWebRequest.ID_PARAMETER, id);
  }

  public String getBaseUrl() {
    if (baseUrl == null) {
      HttpServletRequest request = getCurrentRequest();
      String scheme = request.getScheme();
      StringBuilder sb = new StringBuilder();
      sb.append(scheme).append("://").append(request.getServerName());
      int port = request.getServerPort();
      if (("http".equals(scheme) && port != 80) || ("https".equals(scheme) && port != 443)) {
        sb.append(":").append(port);
      }
      String contextPath = request.getContextPath();
      if (contextPath != null) {
        sb.append(contextPath);
      }
      baseUrl = sb.toString();
    }
    return baseUrl;
  }

  public EncodingStateRegistry getEncodingStateRegistry() {
    if (encodingStateRegistry == null) {
      encodingStateRegistry = new DefaultEncodingStateRegistry();
    }
    return encodingStateRegistry;
  }

  private static final class DefaultEncodingStateRegistryLookup
      implements EncodingStateRegistryLookup {
    public EncodingStateRegistry lookup() {
      GrailsWebRequest webRequest = GrailsWebRequest.lookup();
      return webRequest == null ? null : webRequest.getEncodingStateRegistry();
    }
  }

  static {
    EncodingStateRegistryLookupHolder.setEncodingStateRegistryLookup(
        new DefaultEncodingStateRegistryLookup());
  }

  /**
   * @return true if grails.views.filteringCodecForMimeType settings should be ignored for this
   *     request
   */
  public boolean isSkipFilteringCodec() {
    return skipFilteringCodec;
  }

  public void setSkipFilteringCodec(boolean skipCodec) {
    this.skipFilteringCodec = skipCodec;
  }

  public String getFilteringCodec() {
    return filteringEncoder != null ? filteringEncoder.getCodecIdentifier().getCodecName() : null;
  }

  public void setFilteringCodec(String codecName) {
    filteringEncoder =
        codecName != null
            ? CodecLookupHelper.lookupEncoder(attributes.getGrailsApplication(), codecName)
            : null;
  }

  public Encoder lookupFilteringEncoder() {
    if (filteringEncoder == null
        && applicationContext != null
        && applicationContext.containsBean(FilteringCodecsByContentTypeSettings.BEAN_NAME)) {
      filteringEncoder =
          applicationContext
              .getBean(
                  FilteringCodecsByContentTypeSettings.BEAN_NAME,
                  FilteringCodecsByContentTypeSettings.class)
              .getEncoderForContentType(getResponse().getContentType());
    }
    return filteringEncoder;
  }

  public Encoder getFilteringEncoder() {
    return filteringEncoder;
  }

  public void setFilteringEncoder(Encoder filteringEncoder) {
    this.filteringEncoder = filteringEncoder;
  }
}
Exemple #2
0
/**
 * Allows looking up key classes in a static context
 *
 * @author Burt Beckwith
 * @author Graeme Rocher
 * @since 2.0
 */
public class Holders {

  private static final Log LOG = LogFactory.getLog(Holders.class);
  private static Holder<GrailsPluginManager> pluginManagers =
      new Holder<GrailsPluginManager>("PluginManager");
  private static Holder<Boolean> pluginManagersInCreation =
      new Holder<Boolean>("PluginManagers in creation");
  private static Holder<Config> configs = new Holder<Config>("config");
  private static Holder<Map<?, ?>> flatConfigs = new Holder<Map<?, ?>>("flat config");

  private static List<GrailsApplicationDiscoveryStrategy> applicationDiscoveryStrategies =
      GrailsFactoriesLoader.loadFactories(
          GrailsApplicationDiscoveryStrategy.class, Holders.class.getClassLoader());
  private static Holder servletContexts;

  static {
    createServletContextsHolder();
  }

  private static GrailsApplication applicationSingleton; // TODO remove

  private Holders() {
    // static only
  }

  public static void addApplicationDiscoveryStrategy(GrailsApplicationDiscoveryStrategy strategy) {
    applicationDiscoveryStrategies.add(strategy);
  }

  public static void clear() {
    pluginManagers.set(null);
    pluginManagersInCreation.set(null);
    configs.set(null);
    flatConfigs.set(null);
    if (servletContexts != null) {
      servletContexts.set(null);
    }
    applicationDiscoveryStrategies.clear();
    applicationSingleton = null;
  }

  public static void setServletContext(final Object servletContext) {
    servletContexts.set(servletContext);
  }

  public static Object getServletContext() {
    return get(servletContexts, "servletContext");
  }

  public static ApplicationContext getApplicationContext() {
    for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
      ApplicationContext applicationContext = strategy.findApplicationContext();
      if (applicationContext != null) {
        boolean running = ((Lifecycle) applicationContext).isRunning();
        if (running) {
          return applicationContext;
        }
      }
    }
    throw new IllegalStateException(
        "Could not find ApplicationContext, configure Grails correctly first");
  }

  /** @return The ApplicationContext or null if it doesn't exist */
  public static ApplicationContext findApplicationContext() {
    for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
      ApplicationContext applicationContext = strategy.findApplicationContext();
      if (applicationContext != null) {
        return applicationContext;
      }
    }
    return null;
  }
  /** @return The ApplicationContext or null if it doesn't exist */
  public static GrailsApplication findApplication() {
    for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
      GrailsApplication grailsApplication = strategy.findGrailsApplication();
      if (grailsApplication != null) {
        return grailsApplication;
      }
    }
    return applicationSingleton;
  }

  public static GrailsApplication getGrailsApplication() {
    GrailsApplication grailsApplication = findApplication();
    Assert.notNull(grailsApplication, "GrailsApplication not found");
    return grailsApplication;
  }

  public static void setGrailsApplication(GrailsApplication application) {
    applicationSingleton = application;
  }

  public static void setConfig(Config config) {
    configs.set(config);

    // reset flat config
    flatConfigs.set(config == null ? null : config.flatten());
  }

  public static Config getConfig() {
    return get(configs, "config");
  }

  public static Map<?, ?> getFlatConfig() {
    Map<?, ?> flatConfig = get(flatConfigs, "flatConfig");
    return flatConfig == null ? Collections.emptyMap() : flatConfig;
  }

  public static void setPluginManagerInCreation(boolean inCreation) {
    pluginManagersInCreation.set(inCreation);
  }

  public static void setPluginManager(GrailsPluginManager pluginManager) {
    if (pluginManager != null) {
      pluginManagersInCreation.set(false);
    }
    pluginManagers.set(pluginManager);
  }

  public static GrailsPluginManager getPluginManager() {
    return getPluginManager(false);
  }

  public static GrailsPluginManager getPluginManager(boolean mappedOnly) {
    while (true) {
      Boolean inCreation = get(pluginManagersInCreation, "PluginManager in creation", mappedOnly);
      if (inCreation == null) {
        inCreation = false;
      }
      if (!inCreation) {
        break;
      }

      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        break;
      }
    }

    return get(pluginManagers, "PluginManager", mappedOnly);
  }

  public static GrailsPluginManager currentPluginManager() {
    GrailsPluginManager current = getPluginManager();
    Assert.notNull(current, "No PluginManager set");
    return current;
  }

  public static void reset() {
    setPluginManager(null);
    setGrailsApplication(null);
    setServletContext(null);
    setPluginManager(null);
    setPluginManagerInCreation(false);
    setConfig(null);
  }

  private static <T> T get(Holder<T> holder, String type) {
    return get(holder, type, false);
  }

  private static <T> T get(Holder<T> holder, String type, boolean mappedOnly) {
    return holder.get(mappedOnly);
  }

  @SuppressWarnings("unchecked")
  private static void createServletContextsHolder() {
    try {
      Class<?> clazz =
          Holders.class.getClassLoader().loadClass("grails.web.context.WebRequestServletHolder");
      servletContexts = (Holder) clazz.newInstance();
    } catch (ClassNotFoundException e) {
      // shouldn't happen
      LOG.debug(
          "Error initializing servlet context holder, not running in Servlet environment: "
              + e.getMessage(),
          e);
    } catch (InstantiationException e) {
      // shouldn't happen
      LOG.debug(
          "Error initializing servlet context holder, not running in Servlet environment: "
              + e.getMessage(),
          e);
    } catch (IllegalAccessException e) {
      // shouldn't happen
      LOG.debug(
          "Error initializing servlet context holder, not running in Servlet environment: "
              + e.getMessage(),
          e);
    }
  }
}