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.cms.content; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.io.Serializable; 021import java.util.Arrays; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.avalon.framework.parameters.ParameterException; 027import org.apache.avalon.framework.parameters.Parameters; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.cocoon.ProcessingException; 032import org.apache.cocoon.caching.CacheableProcessingComponent; 033import org.apache.cocoon.environment.ObjectModelHelper; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036import org.apache.commons.lang.StringUtils; 037import org.apache.excalibur.source.SourceValidity; 038import org.apache.excalibur.source.impl.validity.TimeStampValidity; 039 040import org.ametys.cms.repository.Content; 041import org.ametys.core.util.URIUtils; 042import org.ametys.core.util.cocoon.AbstractResourceReader; 043import org.ametys.plugins.repository.AmetysObjectResolver; 044import org.ametys.plugins.repository.metadata.BinaryMetadata; 045import org.ametys.plugins.repository.metadata.CompositeMetadata; 046import org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType; 047import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject; 048import org.ametys.plugins.repository.version.VersionableAmetysObject; 049 050/** 051 * Reader for binary or file metadata. 052 */ 053public class FileReader extends AbstractResourceReader implements Serviceable, CacheableProcessingComponent 054{ 055 /** The ametys object resolver. */ 056 protected AmetysObjectResolver _resolver; 057 058 private MetadataAwareAmetysObject _ametysObject; 059 private BinaryMetadata _binary; 060 061 private String _path; 062 063 @Override 064 public void service(ServiceManager serviceManager) throws ServiceException 065 { 066 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 067 } 068 069 @Override 070 public void doSetup(SourceResolver res, Map objModel, String src, Parameters par) throws ProcessingException, IOException 071 { 072 _ametysObject = getAmetysObject(); 073 074 CompositeMetadata metadata = _ametysObject.getMetadataHolder(); 075 076 try 077 { 078 _path = parameters.getParameter("path"); 079 } 080 catch (ParameterException e) 081 { 082 throw new ProcessingException("The path parameter is mandatory for reading binary metadata.", e); 083 } 084 085 List<String> pathElements = Arrays.asList(_path.split("/")); 086 087 Iterator<String> it = pathElements.iterator(); 088 089 while (it.hasNext()) 090 { 091 String pathElement = it.next(); 092 093 if (it.hasNext()) 094 { 095 // not the last segment : it is a composite 096 metadata = metadata.getCompositeMetadata(URIUtils.decode(pathElement)); 097 } 098 else 099 { 100 String metadataName = URIUtils.decode(pathElement); 101 if (metadata.getType(metadataName) != MetadataType.BINARY) 102 { 103 throw new UnsupportedOperationException("Only binary metadata are allowed"); 104 } 105 106 _binary = metadata.getBinaryMetadata(metadataName); 107 } 108 } 109 } 110 111 /** 112 * Get the ametys object. 113 * @return the ametys object. 114 * @throws ProcessingException if the information provided was insufficient to resolve an object. 115 */ 116 protected MetadataAwareAmetysObject getAmetysObject() throws ProcessingException 117 { 118 MetadataAwareAmetysObject object = null; 119 120 Request request = ObjectModelHelper.getRequest(objectModel); 121 String objectPath = parameters.getParameter("objectPath", request.getParameter("objectPath")); 122 String objectId = parameters.getParameter("objectId", request.getParameter("objectId")); 123 // Legacy parameter name. 124 if (StringUtils.isBlank(objectId)) 125 { 126 objectId = parameters.getParameter("contentId", request.getParameter("contentId")); 127 } 128 129 if (StringUtils.isNotBlank(objectId)) 130 { 131 object = _resolver.resolveById(objectId); 132 } 133 else if (StringUtils.isNotBlank(objectPath)) 134 { 135 objectPath = objectPath.replaceAll("%3A", ":"); 136 object = _resolver.resolveByPath(objectPath); 137 } 138 else 139 { 140 object = (Content) request.getAttribute(Content.class.getName()); 141 } 142 143 if (object == null) 144 { 145 throw new ProcessingException("The object ID parameter is mandatory for reading binary metadata."); 146 } 147 148 String revision = parameters.getParameter("contentVersion", null); 149 if (StringUtils.isNotEmpty(revision) && object instanceof VersionableAmetysObject) 150 { 151 ((VersionableAmetysObject) object).switchToRevision(revision); 152 } 153 154 return object; 155 } 156 157 @Override 158 protected InputStream getInputStream() 159 { 160 return _binary.getInputStream(); 161 } 162 163 @Override 164 protected String getFilename() 165 { 166 return _binary.getFilename(); 167 } 168 169 @Override 170 protected String getEncodedFilename() 171 { 172 return null; 173 } 174 175 @Override 176 protected long getLength() 177 { 178 return _binary.getLength(); 179 } 180 181 @Override 182 public Serializable getKey() 183 { 184 return _ametysObject.getId() + ";" + _path + getKeySuffix(); 185 } 186 187 @Override 188 public SourceValidity getValidity() 189 { 190 return new TimeStampValidity(getLastModified()); 191 } 192 193 @Override 194 public long getLastModified() 195 { 196 if (_binary != null) 197 { 198 return _binary.getLastModified().getTime(); 199 } 200 201 return super.getLastModified(); 202 } 203 204 @Override 205 public String getMimeType() 206 { 207 if (_binary != null) 208 { 209 return _binary.getMimeType(); 210 } 211 212 return super.getMimeType(); 213 } 214 215 @Override 216 public void recycle() 217 { 218 super.recycle(); 219 220 _binary = null; 221 _ametysObject = null; 222 } 223}