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.transformation; 017 018import java.io.InputStream; 019import java.util.Collections; 020 021import org.apache.avalon.framework.context.Context; 022import org.apache.avalon.framework.context.ContextException; 023import org.apache.avalon.framework.context.Contextualizable; 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; 028import org.apache.cocoon.components.ContextHelper; 029import org.apache.cocoon.environment.Request; 030 031import org.ametys.cms.URIPrefixHandler; 032import org.ametys.cms.repository.Content; 033import org.ametys.cms.transformation.ConsistencyChecker.CHECK; 034import org.ametys.core.util.URLEncoder; 035import org.ametys.plugins.explorer.resources.Resource; 036import org.ametys.plugins.repository.AmetysObject; 037import org.ametys.plugins.repository.AmetysObjectResolver; 038import org.ametys.plugins.repository.UnknownAmetysObjectException; 039import org.ametys.runtime.i18n.I18nizableText; 040 041/** 042 * {@link URIResolver} for type "attachment".<br> 043 * These links point to a file from the attachments of the current Content. 044 */ 045public class AttachmentURIResolver extends AbstractLogEnabled implements URIResolver, Serviceable, Contextualizable 046{ 047 /** The ametys resolver */ 048 protected AmetysObjectResolver _resolver; 049 /** The avalon context */ 050 protected Context _context; 051 /** The URI prefix handler */ 052 protected URIPrefixHandler _prefixHandler; 053 054 @Override 055 public void contextualize(Context context) throws ContextException 056 { 057 _context = context; 058 } 059 060 @Override 061 public void service(ServiceManager manager) throws ServiceException 062 { 063 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 064 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 065 } 066 067 @Override 068 public String getType() 069 { 070 return "attachment-content"; 071 } 072 073 @Override 074 public String resolve(String uri, boolean download, boolean absolute, boolean internal) 075 { 076 Request request = ContextHelper.getRequest(_context); 077 String path; 078 Content content = null; 079 String contentName = null; 080 081 try 082 { 083 Resource resource = (Resource) _resolver.resolveById(uri); 084 path = resource.getResourcePath(); 085 086 content = (Content) request.getAttribute(Content.class.getName()); 087 contentName = content.getName(); 088 } 089 catch (UnknownAmetysObjectException e) 090 { 091 getLogger().warn("Link to unexisting resource " + uri); 092 return ""; 093 } 094 catch (Exception e) 095 { 096 throw new IllegalStateException(e); 097 } 098 099 StringBuilder resultPath = new StringBuilder(); 100 resultPath.append(getUriPrefix(content, download, internal, absolute)); 101 102 resultPath.append("/_attachments/") 103 .append(contentName) 104 .append(path); 105 106 String encodePath = URLEncoder.encodePath(resultPath.toString()); 107 return URLEncoder.encodeURI(encodePath, download ? Collections.singletonMap("download", "true") : null); 108 } 109 110 /** 111 * Get the URI prefix 112 * @param object The object 113 * @param download true if the pointed resource is to be downloaded. 114 * @param absolute true if the url must be absolute 115 * @param internal true to get an internal URI. 116 * @return the URI prefix 117 */ 118 protected String getUriPrefix (AmetysObject object, boolean download, boolean internal, boolean absolute) 119 { 120 if (internal) 121 { 122 return "cocoon://"; 123 } 124 else if (absolute) 125 { 126 return _prefixHandler.getAbsoluteUriPrefix(); 127 } 128 else 129 { 130 return _prefixHandler.getUriPrefix(); 131 } 132 } 133 134 @Override 135 public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal) 136 { 137 if (height == 0 && width == 0) 138 { 139 return resolve(uri, download, absolute, internal); 140 } 141 142 Request request = ContextHelper.getRequest(_context); 143 String path; 144 Content content = null; 145 String contentName = null; 146 try 147 { 148 Resource resource = (Resource) _resolver.resolveById(uri); 149 path = resource.getResourcePath(); 150 151 content = (Content) request.getAttribute(Content.class.getName()); 152 contentName = content.getName(); 153 } 154 catch (UnknownAmetysObjectException e) 155 { 156 getLogger().warn("Link to unexisting resource " + uri); 157 return ""; 158 } 159 catch (Exception e) 160 { 161 throw new IllegalStateException(e); 162 } 163 164 int i = path.lastIndexOf("."); 165 String extension = path.substring(i); 166 path = path.substring(0, i); 167 168 StringBuilder result = new StringBuilder(); 169 result.append(getUriPrefix(content, download, internal, absolute)); 170 171 result.append("/_attachments-images/") 172 .append(contentName) 173 .append(path) 174 .append("_").append(height).append("x").append(width) 175 .append(extension); 176 177 String encodePath = URLEncoder.encodePath(result.toString()); 178 return URLEncoder.encodeURI(encodePath, download ? Collections.singletonMap("download", "true") : null); 179 } 180 181 @Override 182 public String resolveImageAsBase64(String uri, int height, int width) 183 { 184 return resolveImageAsBase64(uri, height, width, 0, 0); 185 } 186 187 @Override 188 public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal) 189 { 190 if (maxHeight == 0 && maxWidth == 0) 191 { 192 return resolve(uri, download, absolute, internal); 193 } 194 195 Request request = ContextHelper.getRequest(_context); 196 String path; 197 Content content = null; 198 String contentName = null; 199 try 200 { 201 Resource resource = (Resource) _resolver.resolveById(uri); 202 path = resource.getResourcePath(); 203 204 content = (Content) request.getAttribute(Content.class.getName()); 205 contentName = content.getName(); 206 207 } 208 catch (UnknownAmetysObjectException e) 209 { 210 getLogger().warn("Link to unexisting resource " + uri); 211 return ""; 212 } 213 catch (Exception e) 214 { 215 throw new IllegalStateException(e); 216 } 217 218 int i = path.lastIndexOf("."); 219 String extension = path.substring(i); 220 path = path.substring(0, i); 221 222 StringBuilder result = new StringBuilder(); 223 result.append(getUriPrefix(content, download, internal, absolute)); 224 225 result.append("/_attachments-images/") 226 .append(contentName) 227 .append(path) 228 .append("_max").append(maxHeight).append("x").append(maxWidth) 229 .append(extension); 230 231 String encodePath = URLEncoder.encodePath(result.toString()); 232 return URLEncoder.encodeURI(encodePath, download ? Collections.singletonMap("download", "true") : null); 233 } 234 235 @Override 236 public String resolveBoundedImageAsBase64(String uri, int maxHeight, int maxWidth) 237 { 238 return resolveImageAsBase64(uri, 0, 0, maxHeight, maxWidth); 239 } 240 241 /** 242 * Get an image's bytes encoded as base64, optionally resized. 243 * @param uri the image URI. 244 * @param height the specified height. Ignored if negative. 245 * @param width the specified width. Ignored if negative. 246 * @param maxHeight the maximum image height. Ignored if height or width is specified. 247 * @param maxWidth the maximum image width. Ignored if height or width is specified. 248 * @return the image bytes encoded as base64. 249 */ 250 protected String resolveImageAsBase64(String uri, int height, int width, int maxHeight, int maxWidth) 251 { 252 try 253 { 254 Resource resource = (Resource) _resolver.resolveById(uri); 255 256 try (InputStream dataIs = resource.getInputStream()) 257 { 258 return ImageResolverHelper.resolveImageAsBase64(dataIs, resource.getMimeType(), height, width, maxHeight, maxWidth); 259 } 260 } 261 catch (UnknownAmetysObjectException e) 262 { 263 getLogger().warn("Link to unexisting resource " + uri); 264 return ""; 265 } 266 catch (Exception e) 267 { 268 throw new IllegalStateException(e); 269 } 270 } 271 272 @Override 273 public CHECK checkLink(String uri, boolean shortTest) 274 { 275 try 276 { 277 _resolver.resolveById(uri); 278 return CHECK.SUCCESS; 279 } 280 catch (UnknownAmetysObjectException e) 281 { 282 return CHECK.NOT_FOUND; 283 } 284 } 285 286 @Override 287 public I18nizableText getLabel(String uri) 288 { 289 try 290 { 291 Resource resource = (Resource) _resolver.resolveById(uri); 292 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_ATTACHMENT_LABEL", Collections.singletonList(resource.getResourcePath())); 293 } 294 catch (UnknownAmetysObjectException e) 295 { 296 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_ATTACHMENT_UNKNOWN"); 297 } 298 } 299}