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 */ 016 017package org.ametys.site; 018 019import java.util.Map; 020import java.util.UUID; 021 022import org.apache.avalon.framework.parameters.Parameters; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.thread.ThreadSafe; 025import org.apache.cocoon.acting.ServiceableAction; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Redirector; 028import org.apache.cocoon.environment.Request; 029import org.apache.cocoon.environment.SourceResolver; 030import org.apache.commons.lang.StringUtils; 031import org.apache.excalibur.source.Source; 032import org.apache.excalibur.source.SourceNotFoundException; 033import org.apache.excalibur.source.TraversableSource; 034import org.apache.excalibur.source.impl.FileSource; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038import org.ametys.plugins.site.cache.monitoring.Constants; 039import org.ametys.plugins.site.cache.monitoring.process.access.ResourceAccessComponent; 040import org.ametys.plugins.site.cache.monitoring.process.access.impl.FrontResourceAccess; 041 042/** 043 * The cocoon resource exists action but that returns false for folders 044 */ 045public class ResourceExistsAction extends ServiceableAction implements ThreadSafe 046{ 047 /** The resource access monitoring component */ 048 protected ResourceAccessComponent _resourceAccessComponent; 049 050 // FIXME static final logger? 051 private final Logger _logger = LoggerFactory.getLogger("site.cache.log"); 052 053 /** 054 * Get the resource access component 055 * @return the ResourceAccessComponent 056 */ 057 protected ResourceAccessComponent _getResourceAccessComponent() 058 { 059 if (_resourceAccessComponent == null) 060 { 061 try 062 { 063 _resourceAccessComponent = (ResourceAccessComponent) manager.lookup(ResourceAccessComponent.ROLE); 064 } 065 catch (ServiceException e) 066 { 067 throw new IllegalStateException("Cannot get ResourceAccessComponent", e); 068 } 069 } 070 return _resourceAccessComponent; 071 } 072 073 @Override 074 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws Exception 075 { 076 Request request = ObjectModelHelper.getRequest(objectModel); 077 078 // First, only consider HEAD and GET methods 079 String method = request.getMethod(); 080 081 if (!method.equals("HEAD") && !method.equals("GET")) 082 { 083 return null; 084 } 085 086 String resourceURI = parameters.getParameter("url", src); 087 Source source = null; 088 089 // Resource monitoring 090 // the Apache mod_unique_id set a request header "UNIQUE_ID" 091 // that we could use to track request in log files 092 String uniqueId = request.getHeader("UNIQUE_ID"); 093 094 // Set the random uuid as a request attribute to be added later in the possible requests to the BO. 095 String uuid = UUID.randomUUID().toString(); 096 request.setAttribute("Monitoring-UUID", uuid); 097 098 String path = resourceURI; 099 if (StringUtils.startsWith(path, "ametys-home://cache")) 100 { 101 path = StringUtils.removeStart(path, "ametys-home://cache"); 102 } 103 else 104 { 105 path = StringUtils.removeStart(resourceURI, SiteCacheHelper.getRootCache().getPath()); 106 } 107 108 FrontResourceAccess fra = new FrontResourceAccess(uniqueId, uuid, parameters.getParameter("site", null), path); 109 110 try 111 { 112 source = resolver.resolveURI(resourceURI); 113 114 if (source instanceof FileSource && !SiteCacheHelper.isValid((FileSource) source)) 115 { 116 // Release the old source and replace it by a hashed file source. 117 source = SiteCacheHelper.getHashedFileSource(resolver, (FileSource) source); 118 } 119 120 if (source.exists() 121 && (!(source instanceof TraversableSource) || !((TraversableSource) source).isCollection())) 122 { 123 if (_logger.isDebugEnabled()) 124 { 125 _logger.debug("Find resource '" + resourceURI + " in cache"); 126 } 127 128 fra.setCacheable(true); 129 fra.setCacheHit1(true); 130 _getResourceAccessComponent().addAccessRecord(fra); 131 132 return EMPTY_MAP; 133 } 134 } 135 catch (SourceNotFoundException e) 136 { 137 // Do not log 138 } 139 catch (Exception e) 140 { 141 getLogger().warn("Exception resolving resource " + resourceURI, e); 142 } 143 finally 144 { 145 if (source != null) 146 { 147 resolver.release(source); 148 } 149 } 150 151 fra.setCacheHit1(false); 152 request.setAttribute(Constants.REQUEST_ATTRIBUTE_PAGEACCESS, fra); 153 154 return null; 155 } 156 157}