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.repository.site.Site;
040import org.ametys.web.service.Service;
041import org.ametys.web.service.ServiceExtensionPoint;
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    
055    @Override
056    public void service(ServiceManager serviceManager) throws ServiceException
057    {
058        _serviceExtPt = (ServiceExtensionPoint) serviceManager.lookup(ServiceExtensionPoint.ROLE);
059        _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE);
060        _inputDataExtensionPoint = (InputDataExtensionPoint) serviceManager.lookup(InputDataExtensionPoint.ROLE);
061    }
062    
063    /**
064     * Tests if a page is cacheable, i.e:<ul>
065     * <li>its access is not restricted</li>
066     * <li>all its page elements are cachable</li>
067     * </ul>
068     * @param page The page to test.
069     * @return true if the page is cachable, false otherwise.
070     */
071    public boolean isCacheable(Page page)
072    {
073        if (!_rightManager.hasAnonymousReadAccess(page))
074        {
075            // never cache a private page
076            return false;
077        }
078        
079        if (page.getType() != PageType.CONTAINER)
080        {
081            // makes no sense to cache a Node or link page
082            return false;
083        }
084        
085        boolean isCacheable = true;
086        AmetysObjectIterable<? extends Zone> zones = page.getZones();
087        Iterator<? extends Zone> itZ = zones.iterator();
088        
089        // test each service of the page
090        while (isCacheable && itZ.hasNext())
091        {
092            Zone zone = itZ.next();
093            AmetysObjectIterable<? extends ZoneItem> zoneItems = zone.getZoneItems();
094            Iterator<? extends ZoneItem> itZI = zoneItems.iterator();
095            
096            while (isCacheable && itZI.hasNext())
097            {
098                ZoneItem zoneItem = itZI.next();
099                if (zoneItem.getType() == ZoneType.SERVICE)
100                {
101                    Service service = _serviceExtPt.getExtension(zoneItem.getServiceId());
102                    try
103                    {
104                        isCacheable = service != null && service.isCacheable(page, zoneItem);
105                    }
106                    catch (Exception e)
107                    {
108                        // Ignore
109                    }
110                }
111            }
112        }
113        
114        // Test each inputdata
115        if (isCacheable)
116        {
117            Collection<String> ids = _inputDataExtensionPoint.getExtensionsIds();
118            Iterator<String> it = ids.iterator();
119            while (isCacheable && it.hasNext())
120            {
121                String id = it.next();
122                InputData inputData = _inputDataExtensionPoint.getExtension(id);
123                isCacheable = inputData.isCacheable(page.getSite(), page);
124            }
125        }
126        
127        return isCacheable;
128    }
129    
130    /**
131     * Determines if a captcha is required on forms of the page
132     * @param page The page to test
133     * @return  true if a captcha is required
134     */
135    public boolean isCaptchaRequired (Page page)
136    {
137        Site site = page.getSite();
138        
139        String captchaPolicy = site.getValue("display-captcha-policy");
140        
141        if (captchaPolicy == null || "restricted".equals(captchaPolicy)) 
142        {
143            // Display captcha on public page only
144            return _rightManager.hasAnonymousReadAccess(page); 
145        }
146        
147        return "always".equals(captchaPolicy);
148    }
149
150    /**
151     * Get all the contents inside a page
152     * @param page page to search
153     * @return list of contents in this page
154     */
155    public List<Content> getAllContents (Page page)
156    {
157        List<Content> result = new ArrayList<>();
158        AmetysObjectIterable< ? extends Zone> zones = page.getZones();
159        for (Zone zone : zones)
160        {
161            AmetysObjectIterable< ? extends ZoneItem> zoneItems = zone.getZoneItems();
162            for (ZoneItem zoneItem : zoneItems)
163            {
164                if (ZoneType.CONTENT.equals(zoneItem.getType()))
165                {
166                    Content content = zoneItem.getContent();
167                    result.add(content);
168                }
169            }
170        }
171        return result;
172    }
173
174}