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