001/* 002 * Copyright 2015 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.cache; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Iterator; 021import java.util.List; 022 023import org.apache.avalon.framework.component.Component; 024import org.apache.avalon.framework.logger.AbstractLogEnabled; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.avalon.framework.service.Serviceable; 028 029import org.ametys.cms.repository.Content; 030import org.ametys.core.right.RightManager; 031import org.ametys.plugins.repository.AmetysObjectIterable; 032import org.ametys.web.inputdata.InputData; 033import org.ametys.web.inputdata.InputDataExtensionPoint; 034import org.ametys.web.repository.page.Page; 035import org.ametys.web.repository.page.Page.PageType; 036import org.ametys.web.repository.page.Zone; 037import org.ametys.web.repository.page.ZoneItem; 038import org.ametys.web.repository.page.ZoneItem.ZoneType; 039import org.ametys.web.service.Service; 040import org.ametys.web.service.ServiceExtensionPoint; 041import org.ametys.web.site.SiteConfigurationExtensionPoint; 042 043/** 044 * Helper component providing status of pages. 045 */ 046public class PageHelper extends AbstractLogEnabled implements Component, Serviceable 047{ 048 /** The component role. */ 049 public static final String ROLE = PageHelper.class.getName(); 050 051 private ServiceExtensionPoint _serviceExtPt; 052 private RightManager _rightManager; 053 private InputDataExtensionPoint _inputDataExtensionPoint; 054 private SiteConfigurationExtensionPoint _siteConfiguration; 055 056 @Override 057 public void service(ServiceManager serviceManager) throws ServiceException 058 { 059 _serviceExtPt = (ServiceExtensionPoint) serviceManager.lookup(ServiceExtensionPoint.ROLE); 060 _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE); 061 _inputDataExtensionPoint = (InputDataExtensionPoint) serviceManager.lookup(InputDataExtensionPoint.ROLE); 062 _siteConfiguration = (SiteConfigurationExtensionPoint) serviceManager.lookup(SiteConfigurationExtensionPoint.ROLE); 063 } 064 065 /** 066 * Tests if a page is cacheable, i.e:<ul> 067 * <li>its access is not restricted</li> 068 * <li>all its page elements are cachable</li> 069 * </ul> 070 * @param page The page to test. 071 * @return true if the page is cachable, false otherwise. 072 */ 073 public boolean isCacheable(Page page) 074 { 075 if (!_rightManager.hasAnonymousReadAccess(page)) 076 { 077 // never cache a private page 078 return false; 079 } 080 081 if (page.getType() != PageType.CONTAINER) 082 { 083 // makes no sense to cache a Node or link page 084 return false; 085 } 086 087 boolean isCacheable = true; 088 AmetysObjectIterable<? extends Zone> zones = page.getZones(); 089 Iterator<? extends Zone> itZ = zones.iterator(); 090 091 // test each service of the page 092 while (isCacheable && itZ.hasNext()) 093 { 094 Zone zone = itZ.next(); 095 AmetysObjectIterable<? extends ZoneItem> zoneItems = zone.getZoneItems(); 096 Iterator<? extends ZoneItem> itZI = zoneItems.iterator(); 097 098 while (isCacheable && itZI.hasNext()) 099 { 100 ZoneItem zoneItem = itZI.next(); 101 if (zoneItem.getType() == ZoneType.SERVICE) 102 { 103 Service service = _serviceExtPt.getExtension(zoneItem.getServiceId()); 104 try 105 { 106 isCacheable = service != null && service.isCacheable(page, zoneItem); 107 } 108 catch (Exception e) 109 { 110 // Ignore 111 } 112 } 113 } 114 } 115 116 // Test each inputdata 117 if (isCacheable) 118 { 119 Collection<String> ids = _inputDataExtensionPoint.getExtensionsIds(); 120 Iterator<String> it = ids.iterator(); 121 while (isCacheable && it.hasNext()) 122 { 123 String id = it.next(); 124 InputData inputData = _inputDataExtensionPoint.getExtension(id); 125 isCacheable = inputData.isCacheable(page.getSite(), page); 126 } 127 } 128 129 return isCacheable; 130 } 131 132 /** 133 * Determines if a captcha is required on forms of the page 134 * @param page The page to test 135 * @return true if a captcha is required 136 */ 137 public boolean isCaptchaRequired (Page page) 138 { 139 String siteName = page.getSiteName(); 140 141 String captchaPolicy = _siteConfiguration.getValueAsString(siteName, "display-captcha-policy"); 142 143 if (captchaPolicy == null || "restricted".equals(captchaPolicy)) 144 { 145 // Display captcha on public page only 146 return _rightManager.hasAnonymousReadAccess(page); 147 } 148 149 return "always".equals(captchaPolicy); 150 } 151 152 /** 153 * Get all the contents inside a page 154 * @param page page to search 155 * @return list of contents in this page 156 */ 157 public List<Content> getAllContents (Page page) 158 { 159 List<Content> result = new ArrayList<>(); 160 AmetysObjectIterable< ? extends Zone> zones = page.getZones(); 161 for (Zone zone : zones) 162 { 163 AmetysObjectIterable< ? extends ZoneItem> zoneItems = zone.getZoneItems(); 164 for (ZoneItem zoneItem : zoneItems) 165 { 166 if (ZoneType.CONTENT.equals(zoneItem.getType())) 167 { 168 Content content = zoneItem.getContent(); 169 result.add(content); 170 } 171 } 172 } 173 return result; 174 } 175 176}