001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.web.inputdata; 017 018import org.apache.avalon.framework.service.ServiceException; 019import org.apache.avalon.framework.service.ServiceManager; 020import org.apache.cocoon.ProcessingException; 021import org.apache.cocoon.environment.ObjectModelHelper; 022import org.apache.cocoon.environment.Request; 023import org.apache.cocoon.generation.ServiceableGenerator; 024import org.apache.cocoon.xml.SaxBuffer; 025import org.apache.cocoon.xml.XMLUtils; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028import org.xml.sax.ContentHandler; 029import org.xml.sax.SAXException; 030 031import org.ametys.plugins.repository.provider.WorkspaceSelector; 032import org.ametys.web.cache.monitoring.Constants; 033import org.ametys.web.cache.monitoring.process.access.ResourceAccessComponent; 034import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess; 035import org.ametys.web.cache.monitoring.process.access.impl.PageElementResourceAccess.PageElementType; 036import org.ametys.web.cache.monitoring.process.access.impl.PageResourceAccess; 037import org.ametys.web.cache.pageelement.PageElementCache; 038import org.ametys.web.renderingcontext.RenderingContext; 039import org.ametys.web.renderingcontext.RenderingContextHandler; 040import org.ametys.web.repository.page.Page; 041import org.ametys.web.repository.site.Site; 042import org.ametys.web.repository.site.SiteManager; 043 044/** 045 * Generates SAX events from activated input data. 046 */ 047public class InputDataGenerator extends ServiceableGenerator 048{ 049 private InputDataExtensionPoint _inputDataExtensionPoint; 050 private PageElementCache _inputDataCache; 051 private WorkspaceSelector _workspaceSelector; 052 private RenderingContextHandler _renderingContextHandler; 053 private SiteManager _sitesManager; 054 055 /** The resource access monitoring component */ 056 private ResourceAccessComponent _resourceAccessMonitor; 057 058 private Logger _timeLogger = LoggerFactory.getLogger("org.ametys.web.rendering.time"); 059 060 @Override 061 public void service(ServiceManager sManager) throws ServiceException 062 { 063 super.service(sManager); 064 _inputDataExtensionPoint = (InputDataExtensionPoint) sManager.lookup(InputDataExtensionPoint.ROLE); 065 _inputDataCache = (PageElementCache) sManager.lookup(PageElementCache.ROLE + "/inputData"); 066 _renderingContextHandler = (RenderingContextHandler) sManager.lookup(RenderingContextHandler.ROLE); 067 _workspaceSelector = (WorkspaceSelector) sManager.lookup(WorkspaceSelector.ROLE); 068 _sitesManager = (SiteManager) sManager.lookup(SiteManager.ROLE); 069 _resourceAccessMonitor = (ResourceAccessComponent) sManager.lookup(ResourceAccessComponent.ROLE); 070 } 071 072 @Override 073 public void generate() throws SAXException, ProcessingException 074 { 075 long t0 = System.currentTimeMillis(); 076 077 Request request = ObjectModelHelper.getRequest(objectModel); 078 079 String siteName; 080 Site site; 081 String pageId = null; 082 083 Page page = (Page) request.getAttribute(Page.class.getName()); 084 if (page != null) 085 { 086 pageId = page.getId(); 087 site = page.getSite(); 088 siteName = page.getSiteName(); 089 } 090 else 091 { 092 siteName = (String) request.getAttribute("site"); 093 site = _sitesManager.getSite(siteName); 094 // there's no current page, set the pageId to the current sitemap name, so that the cached element may depend on the language 095 pageId = (String) request.getAttribute("sitemapLanguage"); 096 } 097 098 String workspace = _workspaceSelector.getWorkspace(); 099 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 100 101 // Access monitoring 102 PageResourceAccess pageAccess = (PageResourceAccess) request.getAttribute(Constants.REQUEST_ATTRIBUTE_PAGEACCESS); 103 104 contentHandler.startDocument(); 105 XMLUtils.startElement(contentHandler, "inputData"); 106 107 for (String id : _inputDataExtensionPoint.getExtensionsIds()) 108 { 109 long t1 = System.currentTimeMillis(); 110 111 InputData inputData = _inputDataExtensionPoint.getExtension(id); 112 113 PageElementResourceAccess inputDataAccess = pageAccess != null ? pageAccess.createPageElementAccess(id, PageElementType.INPUTDATA) : null; 114 115 116 // Only lookup cached content if it should be cached, to avoid missed get on elements that wont be on the cache 117 boolean isCacheable = inputData.isCacheable(site, page); 118 boolean shouldBeCached = isCacheable && inputData.shouldBeCached(site, page); 119 SaxBuffer cachedContent = null; 120 if (shouldBeCached) 121 { 122 cachedContent = _inputDataCache.getPageElement(workspace, siteName, id, pageId, renderingContext); 123 } 124 125 if (cachedContent != null) 126 { 127 if (inputDataAccess != null) 128 { 129 inputDataAccess.setCacheable(true); 130 inputDataAccess.setCacheHit(true); 131 } 132 133 if (getLogger().isDebugEnabled()) 134 { 135 getLogger().debug("Inputdata '" + id + "' retrieved from cache."); 136 } 137 138 cachedContent.toSAX(contentHandler); 139 } 140 else 141 { 142 143 if (inputDataAccess != null) 144 { 145 inputDataAccess.setCacheable(isCacheable); 146 inputDataAccess.setCacheHit(false); 147 } 148 149 SaxBuffer buffer = null; 150 ContentHandler handler; // the actual ContentHandler, either the real one, or a buffer 151 if (shouldBeCached) 152 { 153 buffer = new SaxBuffer(); 154 handler = buffer; 155 } 156 else 157 { 158 handler = contentHandler; 159 } 160 161 inputData.toSAX(handler); 162 163 if (getLogger().isDebugEnabled()) 164 { 165 getLogger().debug("Inputdata '" + id + "' processed (" + (isCacheable ? "" : "non ") + "cacheable)."); 166 } 167 168 // finally store the buffered data in the cache and SAX it to the pipeline 169 if (buffer != null) 170 { 171 buffer.toSAX(contentHandler); 172 _inputDataCache.storePageElement(workspace, siteName, id, pageId, renderingContext, buffer); 173 } 174 } 175 176 // Monitor the access to this zone item. 177 if (inputDataAccess != null) 178 { 179 _resourceAccessMonitor.addAccessRecord(inputDataAccess); 180 } 181 182 _timeLogger.debug("Inputdata '{}' processing time: {} ms", id, System.currentTimeMillis() - t1); 183 } 184 185 XMLUtils.endElement(contentHandler, "inputData"); 186 contentHandler.endDocument(); 187 188 _timeLogger.debug("Inputdata total processing time: {} ms", System.currentTimeMillis() - t0); 189 } 190}