2 * Copyright 2004-2005 the original author or authors.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.codehaus
.groovy
.grails
.web
.sitemesh
;
18 import com
.opensymphony
.module
.sitemesh
.Config
;
19 import com
.opensymphony
.module
.sitemesh
.Decorator
;
20 import com
.opensymphony
.module
.sitemesh
.DecoratorMapper
;
21 import com
.opensymphony
.module
.sitemesh
.Page
;
22 import com
.opensymphony
.module
.sitemesh
.mapper
.AbstractDecoratorMapper
;
23 import com
.opensymphony
.module
.sitemesh
.mapper
.DefaultDecorator
;
24 import groovy
.lang
.GroovyObject
;
25 import org
.apache
.commons
.lang
.ArrayUtils
;
26 import org
.apache
.commons
.lang
.StringUtils
;
27 import org
.apache
.commons
.logging
.Log
;
28 import org
.apache
.commons
.logging
.LogFactory
;
29 import org
.codehaus
.groovy
.grails
.commons
.GrailsApplication
;
30 import org
.codehaus
.groovy
.grails
.commons
.GrailsResourceUtils
;
31 import org
.codehaus
.groovy
.grails
.web
.metaclass
.ControllerDynamicMethods
;
32 import org
.codehaus
.groovy
.grails
.web
.pages
.GroovyPageResourceLoader
;
33 import org
.codehaus
.groovy
.grails
.web
.servlet
.GrailsApplicationAttributes
;
34 import org
.springframework
.context
.ApplicationContext
;
35 import org
.springframework
.core
.io
.Resource
;
36 import org
.springframework
.core
.io
.ResourceLoader
;
37 import org
.springframework
.core
.io
.support
.PathMatchingResourcePatternResolver
;
38 import org
.springframework
.web
.context
.support
.WebApplicationContextUtils
;
40 import javax
.servlet
.ServletContext
;
41 import javax
.servlet
.http
.HttpServletRequest
;
42 import java
.io
.IOException
;
43 import java
.util
.Collections
;
44 import java
.util
.HashMap
;
46 import java
.util
.Properties
;
49 * Implements the SiteMesh decorator mapper interface and allows grails views to map to grails layouts
51 * @author Graeme Rocher
54 public class GrailsLayoutDecoratorMapper
extends AbstractDecoratorMapper
implements DecoratorMapper
{
56 private static final String DEFAULT_DECORATOR_PATH
= GrailsApplicationAttributes
.PATH_TO_VIEWS
+"/layouts";
57 private static final String DEFAULT_VIEW_TYPE
= ".gsp";
59 private static final Log LOG
= LogFactory
.getLog( GrailsLayoutDecoratorMapper
.class );
62 private Map decoratorMap
= new HashMap();
63 private ServletContext servletContext
;
65 public void init(Config config
, Properties properties
, DecoratorMapper parent
) throws InstantiationException
{
66 super.init(config
,properties
,parent
);
67 this.servletContext
= config
.getServletContext();
71 public Decorator
getDecorator(HttpServletRequest request
, Page page
) {
72 if(LOG
.isDebugEnabled()) {
73 LOG
.debug("Evaluating layout for request: " + request
.getRequestURI());
75 String layoutName
= page
.getProperty("meta.layout");
77 if(StringUtils
.isBlank(layoutName
)) {
78 GroovyObject controller
= (GroovyObject
)request
.getAttribute(GrailsApplicationAttributes
.CONTROLLER
);
79 if(controller
!= null) {
81 String controllerName
= (String
)controller
.getProperty(ControllerDynamicMethods
.CONTROLLER_NAME_PROPERTY
);
82 String actionUri
= (String
)controller
.getProperty(ControllerDynamicMethods
.ACTION_URI_PROPERTY
);
84 if(LOG
.isDebugEnabled())
85 LOG
.debug("Found controller in request, location layout for controller ["+controllerName
+"] and action ["+actionUri
+"]");
88 Decorator d
= getNamedDecorator(request
, actionUri
.substring(1));
91 } else if(!StringUtils
.isBlank(controllerName
)) {
92 if(LOG
.isDebugEnabled())
93 LOG
.debug("Action layout not found, trying controller");
95 d
= getNamedDecorator(request
, controllerName
);
100 return parent
!= null ?
super.getDecorator(request
, page
) : null;
107 return parent
!= null ?
super.getDecorator(request
, page
) : null;
111 if(LOG
.isDebugEnabled()) {
112 LOG
.debug("Evaluated layout for page: " + layoutName
);
114 Decorator d
= getNamedDecorator(request
, layoutName
);
119 return parent
!= null ?
super.getDecorator(request
, page
) : null;
123 public Decorator
getNamedDecorator(HttpServletRequest request
, String name
) {
124 if(StringUtils
.isBlank(name
))return null;
126 if(decoratorMap
.containsKey(name
)) {
127 return (Decorator
)decoratorMap
.get(name
);
130 String decoratorName
= name
;
131 if(!name
.matches("(.+)(\\.)(\\w{2}|\\w{3})")) {
132 name
+= DEFAULT_VIEW_TYPE
;
134 String decoratorPage
= DEFAULT_DECORATOR_PATH
+ '/' + name
;
136 ResourceLoader resourceLoader
= establishResourceLoader();
139 Resource res
= resourceLoader
.getResource(decoratorPage
);
142 PathMatchingResourcePatternResolver matcher
= new PathMatchingResourcePatternResolver(resourceLoader
);
143 String pattern
= GrailsResourceUtils
.WEB_INF
+ "/plugins/*/grails-app/views/layouts/" + name
;
145 if(LOG
.isDebugEnabled())
146 LOG
.debug("No decorator found at " + decoratorPage
+". Trying plug-ins with pattern: " + pattern
);
149 Resource
[] layouts
= matcher
.getResources(pattern
);
150 if(layouts
.length
>0) {
151 if(layouts
.length
>1) {
152 LOG
.warn("Multiple matching layouts found in plug-ins for name ["+name
+"] using first from ["+ ArrayUtils
.toString(layouts
) +"]");
154 String url
= layouts
[0].getURL().toString();
155 url
= GrailsResourceUtils
.WEB_INF
+ url
.substring(url
.indexOf("/plugins"),url
.length());
156 Decorator d
= new DefaultDecorator(name
, request
.getRequestURI(), url
, Collections
.EMPTY_MAP
);
157 decoratorMap
.put(decoratorName
, d
);
160 } catch (IOException e
) {
161 // ignore, if there was a problem here its going to be a FNFE which is ok
163 catch (IllegalArgumentException e
) {
164 // ignore, this is thrown when the plugins dir doesn't exist
169 if(LOG
.isDebugEnabled())
170 LOG
.debug("Using decorator " + decoratorPage
);
172 Decorator d
= new DefaultDecorator(decoratorName
,request
.getRequestURI(),decoratorPage
, Collections
.EMPTY_MAP
);
173 decoratorMap
.put(decoratorName
,d
);
179 private ResourceLoader
establishResourceLoader() {
180 ResourceLoader resourceLoader
;
181 ApplicationContext ctx
= WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext
);
182 GrailsApplication application
= null;
183 if(ctx
.containsBean(GrailsApplication
.APPLICATION_ID
)) {
184 application
= (GrailsApplication
)ctx
.getBean(GrailsApplication
.APPLICATION_ID
);
186 if(application
== null) {
187 resourceLoader
= ctx
;
189 else if(ctx
.containsBean(GroovyPageResourceLoader
.BEAN_ID
) && !application
.isWarDeployed()) {
190 resourceLoader
= (ResourceLoader
)ctx
.getBean(GroovyPageResourceLoader
.BEAN_ID
);
193 resourceLoader
= ctx
;
195 return resourceLoader
;