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; 020import java.util.regex.Matcher; 021import java.util.regex.Pattern; 022 023import org.apache.avalon.framework.context.Context; 024import org.apache.avalon.framework.context.ContextException; 025import org.apache.avalon.framework.context.Contextualizable; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029 030import org.ametys.cms.URIPrefixHandler; 031import org.ametys.cms.repository.Content; 032import org.ametys.cms.transformation.ConsistencyChecker.CHECK; 033import org.ametys.core.util.FilenameUtils; 034import org.ametys.core.util.ImageResolverHelper; 035import org.ametys.core.util.URIUtils; 036import org.ametys.plugins.explorer.resources.Resource; 037import org.ametys.plugins.repository.AmetysObject; 038import org.ametys.plugins.repository.AmetysObjectResolver; 039import org.ametys.plugins.repository.UnknownAmetysObjectException; 040import org.ametys.runtime.i18n.I18nizableText; 041 042/** 043 * {@link URIResolver} for type "attachment".<br> 044 * These links point to a file from the attachments of the current Content. 045 */ 046public class AttachmentURIResolver extends AbstractURIResolver implements Serviceable, Contextualizable 047{ 048 /** Regular expression for contents stored under plugins */ 049 protected static final Pattern __PLUGIN_CONTENT_PATTERN = Pattern.compile("^/ametys:plugins/([^/]+)/ametys:contents/(.*)$"); 050 /** The ametys resolver */ 051 protected AmetysObjectResolver _resolver; 052 /** The avalon context */ 053 protected Context _context; 054 /** The URI prefix handler */ 055 protected URIPrefixHandler _prefixHandler; 056 057 @Override 058 public void contextualize(Context context) throws ContextException 059 { 060 _context = context; 061 } 062 063 @Override 064 public void service(ServiceManager manager) throws ServiceException 065 { 066 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 067 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 068 } 069 070 @Override 071 public String getType() 072 { 073 return "attachment-content"; 074 } 075 076 @Override 077 public String _resolve(String uri, String uriArgument, boolean download, boolean absolute, boolean internal) 078 { 079 String path; 080 Content content = null; 081 String contentName = null; 082 083 try 084 { 085 Resource resource = _resolver.resolveById(uri); 086 path = resource.getResourcePath(); 087 088 AmetysObject ao = resource; 089 do 090 { 091 ao = ao.getParent(); 092 } 093 while (ao != null && !(ao instanceof Content)); 094 095 if (ao == null) 096 { 097 throw new IllegalArgumentException("The given attachment URI should be a content attachment."); 098 } 099 100 content = (Content) ao; 101 contentName = content.getName(); 102 } 103 catch (UnknownAmetysObjectException e) 104 { 105 getLogger().warn("Link to unexisting resource " + uri); 106 return ""; 107 } 108 catch (Exception e) 109 { 110 throw new IllegalStateException(e); 111 } 112 113 String filename = FilenameUtils.encodePath(path); 114 String basePath = org.apache.commons.io.FilenameUtils.removeExtension(filename); 115 String extension = org.apache.commons.io.FilenameUtils.getExtension(filename); 116 117 StringBuilder resultPath = new StringBuilder(); 118 resultPath.append(getUriPrefix(content, download, absolute, internal)); 119 120 Matcher m = __PLUGIN_CONTENT_PATTERN.matcher(content.getPath()); 121 if (m.matches()) 122 { 123 String pluginName = m.group(1); 124 resultPath.append("/") 125 .append(pluginName) 126 .append("/_plugin-attachment/"); 127 } 128 else 129 { 130 resultPath.append("/_attachment/"); 131 } 132 133 resultPath.append(contentName) 134 .append(basePath) 135 .append(uriArgument) 136 .append(extension.isEmpty() ? "" : "." + extension); 137 138 return URIUtils.encodeURI(resultPath.toString(), download ? Collections.singletonMap("download", "true") : null); 139 } 140 141 /** 142 * Get the URI prefix 143 * @param object The object 144 * @param download true if the pointed resource is to be downloaded. 145 * @param absolute true if the url must be absolute 146 * @param internal true to get an internal URI. 147 * @return the URI prefix 148 */ 149 protected String getUriPrefix (AmetysObject object, boolean download, boolean internal, boolean absolute) 150 { 151 return _prefixHandler.computeUriPrefix(absolute, internal); 152 } 153 154 155 @Override 156 protected String resolveImageAsBase64(String uri, int height, int width, int maxHeight, int maxWidth, int cropHeight, int cropWidth) 157 { 158 try 159 { 160 Resource resource = _resolver.resolveById(uri); 161 162 try (InputStream dataIs = resource.getInputStream()) 163 { 164 return ImageResolverHelper.resolveImageAsBase64(dataIs, resource.getMimeType(), height, width, maxHeight, maxWidth, cropHeight, cropWidth); 165 } 166 } 167 catch (UnknownAmetysObjectException e) 168 { 169 getLogger().warn("Link to unexisting resource " + uri); 170 return ""; 171 } 172 catch (Exception e) 173 { 174 throw new IllegalStateException(e); 175 } 176 } 177 178 @Override 179 public CHECK checkLink(String uri, boolean shortTest) 180 { 181 try 182 { 183 _resolver.resolveById(uri); 184 return CHECK.SUCCESS; 185 } 186 catch (UnknownAmetysObjectException e) 187 { 188 return CHECK.NOT_FOUND; 189 } 190 } 191 192 @Override 193 public I18nizableText getLabel(String uri) 194 { 195 try 196 { 197 Resource resource = _resolver.resolveById(uri); 198 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_ATTACHMENT_LABEL", Collections.singletonList(resource.getResourcePath())); 199 } 200 catch (UnknownAmetysObjectException e) 201 { 202 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_ATTACHMENT_UNKNOWN"); 203 } 204 } 205 206 public String getMimeType(String uri) 207 { 208 return _resolver.<Resource>resolveById(uri).getMimeType(); 209 } 210}