001/* 002 * Copyright 2016 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.core.resources; 017 018import java.io.IOException; 019import java.io.Serializable; 020import java.util.Map; 021 022import org.apache.avalon.framework.context.Context; 023import org.apache.avalon.framework.context.ContextException; 024import org.apache.avalon.framework.context.Contextualizable; 025import org.apache.avalon.framework.parameters.Parameters; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.cocoon.Constants; 030import org.apache.cocoon.ProcessingException; 031import org.apache.cocoon.caching.CacheableProcessingComponent; 032import org.apache.cocoon.components.LifecycleHelper; 033import org.apache.cocoon.environment.ObjectModelHelper; 034import org.apache.cocoon.environment.Response; 035import org.apache.cocoon.reading.AbstractReader; 036import org.apache.excalibur.source.Source; 037import org.apache.excalibur.source.SourceResolver; 038import org.apache.excalibur.source.SourceValidity; 039import org.xml.sax.SAXException; 040 041import org.ametys.core.cocoon.source.NamedSource; 042import org.ametys.core.util.URIUtils; 043 044/** 045 * Default resource reader, that handle different resources type using the ResourcesExtensionPoint. 046 */ 047public class ResourceReader extends AbstractReader implements CacheableProcessingComponent, Serviceable, Contextualizable 048{ 049 /** last modified parameter name for resources parameters */ 050 public static final String LAST_MODIFIED = "lastModified"; 051 052 private SourceResolver _resolver; 053 private org.apache.cocoon.environment.Context _cocoonContext; 054 055 private ResourceHandlerProviderExtensionPoint _resourcesHandlerEP; 056 private ResourceHandler _resourceHandler; 057 058 private Source _source; 059 private boolean _readForDownload; 060 061 public void contextualize(Context context) throws ContextException 062 { 063 _cocoonContext = (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 064 } 065 066 public void service(ServiceManager sManager) throws ServiceException 067 { 068 _resourcesHandlerEP = (ResourceHandlerProviderExtensionPoint) sManager.lookup(ResourceHandlerProviderExtensionPoint.ROLE); 069 _resolver = (SourceResolver) sManager.lookup(SourceResolver.ROLE); 070 } 071 072 @Override 073 public void setup(org.apache.cocoon.environment.SourceResolver res, Map objectModel, String source, Parameters parameters) throws ProcessingException, SAXException, IOException 074 { 075 try 076 { 077 _resourceHandler = _resourcesHandlerEP.getResourceHandler(source); 078 } 079 catch (Exception e) 080 { 081 throw new ProcessingException("Exception while retrieving resource handler for resource '" + source + "'", e); 082 } 083 084 _readForDownload = parameters.getParameterAsBoolean("download", false); 085 _source = _resourceHandler.setup(source, objectModel, parameters, _readForDownload); 086 087 // Minimizer does not receive the real lastModified through sitemap source 088 @SuppressWarnings("unchecked") 089 Map<String, Object> params = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 090 if (params != null) 091 { 092 params.put(LAST_MODIFIED, getLastModified()); 093 } 094 095 if (_readForDownload) 096 { 097 String name = _source instanceof NamedSource ? URIUtils.encodeHeader(((NamedSource) _source).getName()) : null; 098 099 Response response = ObjectModelHelper.getResponse(objectModel); 100 response.setHeader("Content-Disposition", "attachment" + (name != null ? ";filename=\"" + name + "\";filename*=UTF-8''" + name : "")); 101 } 102 } 103 104 @Override 105 public void generate() throws IOException, ProcessingException 106 { 107 _resourceHandler.generate(out); 108 out.flush(); 109 } 110 111 @Override 112 public Serializable getKey() 113 { 114 return _resourceHandler.getKey(); 115 } 116 117 @Override 118 public SourceValidity getValidity() 119 { 120 return _resourceHandler.getValidity(); 121 } 122 123 @Override 124 public void recycle() 125 { 126 super.recycle(); 127 128 _resolver.release(_source); 129 LifecycleHelper.dispose(_resourceHandler); 130 } 131 132 @Override 133 public String getMimeType() 134 { 135 String sourceMimeType = _source.getMimeType(); 136 137 if (sourceMimeType != null) 138 { 139 return sourceMimeType; 140 } 141 142 if (_cocoonContext != null) 143 { 144 final String mimeType = _cocoonContext.getMimeType(_source.getURI()); 145 146 if (mimeType != null) 147 { 148 return mimeType; 149 } 150 } 151 152 return null; 153 } 154 155 @Override 156 public long getLastModified() 157 { 158 return _resourceHandler.getLastModified(); 159 } 160}