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