Java tutorial
/* * Copyright (C) 2007-2013 Crafter Software Corporation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.craftercms.engine.view; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.craftercms.core.util.ExceptionUtils; import org.craftercms.core.util.cache.CachingAwareObject; import org.craftercms.engine.exception.HttpStatusCodeAwareException; import org.craftercms.engine.exception.RenderingException; import org.craftercms.engine.model.SiteItem; import org.craftercms.engine.scripting.Script; import org.craftercms.engine.service.SiteItemService; import org.craftercms.engine.util.GroovyScriptUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Required; import org.springframework.http.MediaType; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.AbstractView; /** * @author Alfonso Vsquez */ public class CrafterPageView extends AbstractView implements CachingAwareObject, InitializingBean { private static final Log logger = LogFactory.getLog(CrafterPageView.class); public static final String PAGE_URL_ATTRIBUTE_NAME = "pageUrl"; public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8"; public static final String DEFAULT_CHARSET = "UTF-8"; @Deprecated public static final String KEY_MODEL = "model"; public static final String KEY_CONTENT_MODEL = "contentModel"; protected transient String scope; protected transient Object key; protected transient List<Object> dependencyKeys; protected transient Long cachingTime; protected SiteItem page; protected Locale locale; protected SiteItemService siteItemService; protected String pageViewNameXPathQuery; protected String mimeTypeXPathQuery; protected List<Script> scripts; protected ViewResolver delegatedViewResolver; public SiteItem getPage() { return page; } @Required public void setPage(SiteItem page) { this.page = page; } @Required public void setLocale(Locale locale) { this.locale = locale; } @Required public void setSiteItemService(SiteItemService siteItemService) { this.siteItemService = siteItemService; } @Required public void setPageViewNameXPathQuery(String pageViewNameXPathQuery) { this.pageViewNameXPathQuery = pageViewNameXPathQuery; } @Required public void setMimeTypeXPathQuery(String mimeTypeXPathQuery) { this.mimeTypeXPathQuery = mimeTypeXPathQuery; } @Required public void setScripts(List<Script> scripts) { this.scripts = scripts; } @Required public void setDelegatedViewResolver(ViewResolver delegatedViewResolver) { this.delegatedViewResolver = delegatedViewResolver; } @Override public String getScope() { return scope; } @Override public void setScope(String scope) { this.scope = scope; } @Override public Object getKey() { return key; } @Override public void setKey(Object key) { this.key = key; } @Override public List<Object> getDependencyKeys() { return dependencyKeys; } @Override public void setDependencyKeys(List<Object> dependencyKeys) { this.dependencyKeys = dependencyKeys; } @Override public void addDependencyKeys(Collection<Object> dependencyKeys) { if (this.dependencyKeys == null) { this.dependencyKeys = new ArrayList<>(); } this.dependencyKeys.addAll(dependencyKeys); } @Override public void addDependencyKey(Object dependencyKey) { if (dependencyKeys == null) { dependencyKeys = new ArrayList<>(); } dependencyKeys.add(dependencyKey); } @Override public boolean removeDependencyKeys(Collection<Object> dependencyKeys) { if (this.dependencyKeys != null) { return this.dependencyKeys.removeAll(dependencyKeys); } else { return false; } } @Override public boolean removeDependencyKey(Object dependencyKey) { if (dependencyKeys != null) { return dependencyKeys.remove(dependencyKey); } else { return false; } } @Override public Long getCachingTime() { return cachingTime; } @Override public void setCachingTime(Long cachingTime) { this.cachingTime = cachingTime; } @Override public String toString() { return "CrafterPageView[" + "page=" + page + ", locale=" + locale + ']'; } @Override public void afterPropertiesSet() throws Exception { String mimeType = getMimeType(); if (StringUtils.isNotEmpty(mimeType)) { setContentType(MediaType.parseMediaType(mimeType).toString() + ";charset=" + DEFAULT_CHARSET); } else { setContentType(DEFAULT_CONTENT_TYPE); } } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute(PAGE_URL_ATTRIBUTE_NAME, page.getStoreUrl()); Map<String, Object> scriptVariables = createScriptVariables(request, response, model); if (CollectionUtils.isNotEmpty(scripts)) { for (Script script : scripts) { executeScript(script, scriptVariables); // If the response has been already committed by one of the scripts, stop and don't render the view if (response.isCommitted()) { logger.debug("Response already committed by script"); return; } } } model.put(KEY_MODEL, page); model.put(KEY_CONTENT_MODEL, page); renderActualView(getPageViewName(), model, request, response); } protected void executeScript(Script script, Map<String, Object> scriptVariables) throws Exception { try { script.execute(scriptVariables); } catch (Exception e) { logger.error("Error executing page script at " + script.getUrl(), e); Exception cause = (Exception) ExceptionUtils.getThrowableOfType(e, HttpStatusCodeAwareException.class); if (cause != null) { throw cause; } else { throw e; } } } protected Map<String, Object> createScriptVariables(HttpServletRequest request, HttpServletResponse response, Map<String, Object> model) { Map<String, Object> variables = new HashMap<>(); GroovyScriptUtils.addSiteItemScriptVariables(variables, request, response, getServletContext(), page, model); return variables; } protected String getPageViewName() throws RenderingException { String pageViewName = page.getItem().queryDescriptorValue(pageViewNameXPathQuery); if (StringUtils.isNotEmpty(pageViewName)) { return pageViewName; } else { throw new RenderingException("No view name found for " + page); } } protected String getMimeType() { return page.getItem().queryDescriptorValue(mimeTypeXPathQuery); } protected void renderActualView(String pageViewName, Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { View actualView = delegatedViewResolver.resolveViewName(pageViewName, locale); if (actualView == null) { throw new RenderingException("No view was resolved for page view name '" + pageViewName + "'"); } if (actualView instanceof AbstractView) { ((AbstractView) actualView).setContentType(getContentType()); } actualView.render(model, request, response); } }