/** * 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; } }
/** * 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); } } }