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