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}