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}