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.plugins.explorer.resources.readers;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.io.Serializable;
021import java.util.Map;
022
023import org.apache.avalon.framework.parameters.Parameters;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.cocoon.ProcessingException;
028import org.apache.cocoon.ResourceNotFoundException;
029import org.apache.cocoon.caching.CacheableProcessingComponent;
030import org.apache.cocoon.environment.SourceResolver;
031import org.apache.commons.lang.StringUtils;
032import org.apache.excalibur.source.SourceValidity;
033import org.apache.excalibur.source.impl.validity.TimeStampValidity;
034
035import org.ametys.core.right.RightManager;
036import org.ametys.core.user.CurrentUserProvider;
037import org.ametys.core.user.UserIdentity;
038import org.ametys.core.util.FilenameUtils;
039import org.ametys.core.util.cocoon.AbstractResourceReader;
040import org.ametys.plugins.explorer.resources.Resource;
041import org.ametys.plugins.repository.AmetysObjectResolver;
042import org.ametys.plugins.repository.UnknownAmetysObjectException;
043import org.ametys.plugins.repository.version.VersionableAmetysObject;
044import org.ametys.runtime.authentication.AccessDeniedException;
045import org.ametys.runtime.authentication.AuthorizationRequiredException;
046
047/**
048 * Reader for {@link Resource}
049 */
050public class AmetysResourceReader extends AbstractResourceReader implements Serviceable, CacheableProcessingComponent
051{
052    /** The Ametys object resolver */
053    protected AmetysObjectResolver _resolver;
054    /** The resource */
055    protected Resource _object;
056    /** The right manager */
057    protected RightManager _rightManager;
058    /** The current user provider */
059    protected CurrentUserProvider _currentUserProvider;
060    
061    @Override
062    public void service(ServiceManager sManager) throws ServiceException
063    {
064        _resolver = (AmetysObjectResolver) sManager.lookup(AmetysObjectResolver.ROLE);
065        _rightManager = (RightManager) sManager.lookup(RightManager.ROLE);
066        _currentUserProvider = (CurrentUserProvider) sManager.lookup(CurrentUserProvider.ROLE);
067    }
068    
069    @Override
070    protected void doSetup(SourceResolver res, Map objModel, String src, Parameters par) throws ProcessingException, IOException
071    {
072        String id = par.getParameter("id", null);
073        String path = par.getParameter("path", null);
074        String version = par.getParameter("version", null);
075        
076        try
077        {
078            if (id != null)
079            {
080                _object = _resolver.resolveById(id);
081            }
082            else
083            {
084                _object = _resolver.resolveByPath(FilenameUtils.decode(path.substring(1)));
085            }
086
087            // Check user access
088            checkUserAccess();
089            
090            if (!StringUtils.isEmpty(version) && _object instanceof VersionableAmetysObject)
091            {
092                ((VersionableAmetysObject) _object).switchToRevision(version);
093            }
094        }
095        catch (UnknownAmetysObjectException e)
096        {
097            if (id != null)
098            {
099                throw new ResourceNotFoundException(String.format("The resource with id '%s' does not exist", id));
100            }
101            else
102            {
103                throw new ResourceNotFoundException(String.format("The resource at path '%s' does not exist", path));
104            }
105        }
106    }
107    
108    @Override
109    protected InputStream getInputStream()
110    {
111        return _object.getInputStream();
112    }
113    
114    @Override
115    protected String getFilename()
116    {
117        return _object.getName();
118    }
119    
120    @Override
121    protected String getEncodedFilename()
122    {
123        String name = _object.getName();
124        return FilenameUtils.encodeName(name);
125    }
126    
127    @Override
128    protected long getLength()
129    {
130        return _object.getLength();
131    }
132    
133    /**
134     * Check the user access
135     * @throws AuthorizationRequiredException if authorization is required
136     * @throws AccessDeniedException if user has no access
137     */
138    protected void checkUserAccess() throws AuthorizationRequiredException, AccessDeniedException
139    {
140        UserIdentity user = _currentUserProvider.getUser();
141        
142        if (user == null)
143        {
144            // Check anonymous access
145            if (!_rightManager.hasAnonymousReadAccess(_object.getParent()))
146            {
147                throw new AuthorizationRequiredException(null);
148            }
149        }
150        else if (!_rightManager.hasReadAccess(user, _object.getParent()))
151        {
152            throw new AccessDeniedException("User " + user + " has no right to access the resource " + _object.getId());
153        }
154    }
155    
156    @Override
157    public Serializable getKey()
158    {
159        return _object.getId() + getKeySuffix();
160    }
161
162    @Override
163    public SourceValidity getValidity()
164    {
165        return new TimeStampValidity(getLastModified());
166    }
167    
168    @Override
169    public long getLastModified()
170    {
171        return _object.getLastModified().getTime();
172    }
173    
174    @Override
175    public String getMimeType()
176    {
177        return _object.getMimeType();
178    }
179    
180    @Override
181    public void recycle()
182    {
183        super.recycle();
184        _object = null;
185    }
186}