001: /**
002: * Copyright (c) 2003-2007, David A. Czarnecki
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * Redistributions of source code must retain the above copyright notice, this list of conditions and the
009: * following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
011: * following disclaimer in the documentation and/or other materials provided with the distribution.
012: * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
013: * endorse or promote products derived from this software without specific prior written permission.
014: * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
015: * without prior written permission of David A. Czarnecki.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
018: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
019: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
021: * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
022: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
025: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
029: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030: */package org.blojsom.dispatcher.groovy;
031:
032: import groovy.lang.Binding;
033: import groovy.text.SimpleTemplateEngine;
034: import groovy.text.Template;
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.blojsom.BlojsomException;
038: import org.blojsom.blog.Blog;
039: import org.blojsom.dispatcher.Dispatcher;
040: import org.blojsom.util.BlojsomConstants;
041: import org.blojsom.util.BlojsomUtils;
042: import org.codehaus.groovy.syntax.SyntaxException;
043:
044: import javax.servlet.ServletConfig;
045: import javax.servlet.ServletException;
046: import javax.servlet.ServletContext;
047: import javax.servlet.http.HttpServletRequest;
048: import javax.servlet.http.HttpServletResponse;
049: import java.io.IOException;
050: import java.io.InputStreamReader;
051: import java.io.Writer;
052: import java.util.Iterator;
053: import java.util.Map;
054: import java.util.Properties;
055:
056: /**
057: * GroovyDispatcher
058: *
059: * @author David Czarnecki
060: * @since blojsom 3.0
061: * @version $Id: GroovyDispatcher.java,v 1.2 2007/01/17 01:15:46 czarneckid Exp $
062: */
063: public class GroovyDispatcher implements Dispatcher {
064:
065: private Log _logger = LogFactory.getLog(GroovyDispatcher.class);
066:
067: private ServletConfig _servletConfig;
068: private Properties _blojsomProperties;
069:
070: private String _templatesDirectory;
071: private String _blogsDirectory;
072:
073: /**
074: * Default constructor
075: */
076: public GroovyDispatcher() {
077: }
078:
079: /**
080: * Set the properties in use by blojsom
081: *
082: * @param blojsomProperties Properties in use by blojsom
083: */
084: public void setBlojsomProperties(Properties blojsomProperties) {
085: _blojsomProperties = blojsomProperties;
086: }
087:
088: /**
089: * Set the {@link javax.servlet.ServletConfig}
090: *
091: * @param servletConfig {@link javax.servlet.ServletConfig}
092: */
093: public void setServletConfig(ServletConfig servletConfig) {
094: _servletConfig = servletConfig;
095: }
096:
097: /**
098: * Initialization method for blojsom dispatchers
099: *
100: * @throws org.blojsom.BlojsomException If there is an error initializing the dispatcher
101: */
102: public void init() throws BlojsomException {
103: _templatesDirectory = _blojsomProperties.getProperty(
104: BlojsomConstants.TEMPLATES_DIRECTORY_IP,
105: BlojsomConstants.DEFAULT_TEMPLATES_DIRECTORY);
106: _blogsDirectory = _blojsomProperties.getProperty(
107: BlojsomConstants.BLOGS_DIRECTORY_IP,
108: BlojsomConstants.DEFAULT_BLOGS_DIRECTORY);
109: }
110:
111: /**
112: * Dispatch a request and response. A context map is provided for the BlojsomServlet to pass
113: * any required information for use by the dispatcher. The dispatcher is also
114: * provided with the template for the requested flavor along with the content type for the
115: * specific flavor.
116: *
117: * @param httpServletRequest Request
118: * @param httpServletResponse Response
119: * @param blog {@link Blog}
120: * @param context Context map
121: * @param flavorTemplate Template to dispatch to for the requested flavor
122: * @param flavorContentType Content type for the requested flavor
123: * @throws java.io.IOException If there is an exception during IO
124: * @throws javax.servlet.ServletException If there is an exception in dispatching the request
125: */
126: public void dispatch(HttpServletRequest httpServletRequest,
127: HttpServletResponse httpServletResponse, Blog blog,
128: Map context, String flavorTemplate, String flavorContentType)
129: throws IOException, ServletException {
130: httpServletResponse.setContentType(flavorContentType);
131:
132: ServletContext servletContext = _servletConfig
133: .getServletContext();
134:
135: if (!flavorTemplate.startsWith("/")) {
136: flavorTemplate = '/' + flavorTemplate;
137: }
138:
139: String flavorTemplateForPage = null;
140: String pageParameter = BlojsomUtils.getRequestValue(
141: BlojsomConstants.PAGE_PARAM, httpServletRequest, true);
142:
143: if (pageParameter != null) {
144: flavorTemplateForPage = BlojsomUtils.getTemplateForPage(
145: flavorTemplate, pageParameter);
146: if (_logger.isDebugEnabled()) {
147: _logger.debug("Retrieved template for page: "
148: + flavorTemplateForPage);
149: }
150: }
151:
152: Binding binding = new Binding();
153:
154: // Populate the script context with context attributes from the blog
155: Iterator contextIterator = context.keySet().iterator();
156: String contextKey;
157: while (contextIterator.hasNext()) {
158: contextKey = (String) contextIterator.next();
159: binding.setVariable(contextKey, context.get(contextKey));
160: }
161:
162: Writer responseWriter = httpServletResponse.getWriter();
163:
164: SimpleTemplateEngine simpleTemplateEngine = new SimpleTemplateEngine();
165:
166: // Try and look for the original flavor template with page for the individual user
167: if (flavorTemplateForPage != null) {
168: String templateToLoad = BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
169: + _blogsDirectory
170: + blog.getBlogId()
171: + _templatesDirectory
172: + BlojsomUtils
173: .removeInitialSlash(flavorTemplateForPage);
174:
175: if (servletContext.getResource(templateToLoad) != null) {
176: InputStreamReader isr = new InputStreamReader(
177: servletContext
178: .getResourceAsStream(templateToLoad),
179: BlojsomConstants.UTF8);
180:
181: try {
182: Template groovyTemplate = simpleTemplateEngine
183: .createTemplate(isr);
184: groovyTemplate.setBinding(context);
185: groovyTemplate.writeTo(responseWriter);
186: } catch (SyntaxException e) {
187: if (_logger.isErrorEnabled()) {
188: _logger.error(e);
189: }
190: } catch (ClassNotFoundException e) {
191: if (_logger.isErrorEnabled()) {
192: _logger.error(e);
193: }
194: }
195:
196: if (_logger.isDebugEnabled()) {
197: _logger
198: .debug("Dispatched to flavor page template for user: "
199: + templateToLoad);
200: }
201:
202: return;
203: } else {
204: templateToLoad = BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
205: + BlojsomUtils
206: .removeInitialSlash(_templatesDirectory)
207: + BlojsomUtils
208: .removeInitialSlash(flavorTemplateForPage);
209:
210: if (servletContext.getResource(templateToLoad) != null) {
211: // Otherwise, fallback and look for the flavor template with page without including any user information
212: InputStreamReader isr = new InputStreamReader(
213: servletContext
214: .getResourceAsStream(templateToLoad),
215: BlojsomConstants.UTF8);
216:
217: try {
218: Template groovyTemplate = simpleTemplateEngine
219: .createTemplate(isr);
220: groovyTemplate.setBinding(context);
221: groovyTemplate.writeTo(responseWriter);
222: } catch (SyntaxException e) {
223: if (_logger.isErrorEnabled()) {
224: _logger.error(e);
225: }
226: } catch (ClassNotFoundException e) {
227: if (_logger.isErrorEnabled()) {
228: _logger.error(e);
229: }
230: }
231:
232: if (_logger.isDebugEnabled()) {
233: _logger
234: .debug("Dispatched to flavor page template for user: "
235: + templateToLoad);
236: }
237:
238: return;
239: } else {
240: if (_logger.isErrorEnabled()) {
241: _logger
242: .error("Unable to dispatch to flavor page template: "
243: + templateToLoad);
244: }
245: }
246: }
247: } else {
248: // Otherwise, fallback and look for the flavor template for the individual user
249: String templateToLoad = BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
250: + _blogsDirectory
251: + blog.getBlogId()
252: + _templatesDirectory
253: + BlojsomUtils.removeInitialSlash(flavorTemplate);
254:
255: if (servletContext.getResource(templateToLoad) != null) {
256: InputStreamReader isr = new InputStreamReader(
257: servletContext
258: .getResourceAsStream(templateToLoad),
259: BlojsomConstants.UTF8);
260:
261: try {
262: Template groovyTemplate = simpleTemplateEngine
263: .createTemplate(isr);
264: groovyTemplate.setBinding(context);
265: groovyTemplate.writeTo(responseWriter);
266: } catch (SyntaxException e) {
267: if (_logger.isErrorEnabled()) {
268: _logger.error(e);
269: }
270: } catch (ClassNotFoundException e) {
271: if (_logger.isErrorEnabled()) {
272: _logger.error(e);
273: }
274: }
275:
276: if (_logger.isDebugEnabled()) {
277: _logger
278: .debug("Dispatched to flavor template for user: "
279: + templateToLoad);
280: }
281:
282: return;
283: } else {
284: templateToLoad = BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
285: + BlojsomUtils
286: .removeInitialSlash(_templatesDirectory)
287: + BlojsomUtils
288: .removeInitialSlash(flavorTemplate);
289:
290: if (servletContext.getResource(templateToLoad) != null) {
291: // Otherwise, fallback and look for the flavor template without including any user information
292: InputStreamReader isr = new InputStreamReader(
293: servletContext
294: .getResourceAsStream(templateToLoad),
295: BlojsomConstants.UTF8);
296:
297: try {
298: Template groovyTemplate = simpleTemplateEngine
299: .createTemplate(isr);
300: groovyTemplate.setBinding(context);
301: groovyTemplate.writeTo(responseWriter);
302: } catch (SyntaxException e) {
303: if (_logger.isErrorEnabled()) {
304: _logger.error(e);
305: }
306: } catch (ClassNotFoundException e) {
307: if (_logger.isErrorEnabled()) {
308: _logger.error(e);
309: }
310: }
311:
312: if (_logger.isDebugEnabled()) {
313: _logger.debug("Dispatched to flavor template: "
314: + templateToLoad);
315: }
316:
317: return;
318: } else {
319: if (_logger.isErrorEnabled()) {
320: _logger
321: .error("Unable to dispatch to flavor template: "
322: + templateToLoad);
323: }
324: }
325: }
326: }
327:
328: responseWriter.flush();
329: }
330: }
|