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.content;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.io.Serializable;
021import java.util.Arrays;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.avalon.framework.parameters.ParameterException;
027import org.apache.avalon.framework.parameters.Parameters;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031import org.apache.cocoon.ProcessingException;
032import org.apache.cocoon.caching.CacheableProcessingComponent;
033import org.apache.cocoon.environment.ObjectModelHelper;
034import org.apache.cocoon.environment.Request;
035import org.apache.cocoon.environment.SourceResolver;
036import org.apache.commons.lang.StringUtils;
037import org.apache.excalibur.source.SourceValidity;
038import org.apache.excalibur.source.impl.validity.TimeStampValidity;
039
040import org.ametys.cms.repository.Content;
041import org.ametys.core.util.URIUtils;
042import org.ametys.core.util.cocoon.AbstractResourceReader;
043import org.ametys.plugins.repository.AmetysObjectResolver;
044import org.ametys.plugins.repository.metadata.BinaryMetadata;
045import org.ametys.plugins.repository.metadata.CompositeMetadata;
046import org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType;
047import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject;
048import org.ametys.plugins.repository.version.VersionableAmetysObject;
049
050/**
051 * Reader for binary or file metadata.
052 */
053// FIXME remove this class when Workspaces 2.x is only compatible with 4.4.x
054@Deprecated
055public class FileReader extends AbstractResourceReader implements Serviceable, CacheableProcessingComponent
056{
057    /** The ametys object resolver. */
058    protected AmetysObjectResolver _resolver;
059    
060    private MetadataAwareAmetysObject _ametysObject;
061    private BinaryMetadata _binary;
062    
063    private String _path;
064    
065    @Override
066    public void service(ServiceManager serviceManager) throws ServiceException
067    {
068        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
069    }
070    
071    @Override
072    public void doSetup(SourceResolver res, Map objModel, String src, Parameters par) throws ProcessingException, IOException
073    {
074        _ametysObject = getAmetysObject();
075        
076        CompositeMetadata metadata = _ametysObject.getMetadataHolder();
077        
078        try
079        {
080            _path = parameters.getParameter("path");
081        }
082        catch (ParameterException e)
083        {
084            throw new ProcessingException("The path parameter is mandatory for reading binary metadata.", e);
085        }
086        
087        List<String> pathElements = Arrays.asList(_path.split("/"));
088        
089        Iterator<String> it = pathElements.iterator();
090        
091        while (it.hasNext())
092        {
093            String pathElement = it.next();
094            
095            if (it.hasNext())
096            {
097                // not the last segment : it is a composite
098                metadata = metadata.getCompositeMetadata(URIUtils.decode(pathElement));
099            }
100            else
101            {
102                String metadataName = URIUtils.decode(pathElement);
103                if (metadata.getType(metadataName) != MetadataType.BINARY)
104                {
105                    throw new UnsupportedOperationException("Only binary metadata are allowed");
106                }
107                
108                _binary = metadata.getBinaryMetadata(metadataName);
109            }
110        }
111    }
112
113    /**
114     * Get the ametys object.
115     * @return the ametys object.
116     * @throws ProcessingException if the information provided was insufficient to resolve an object.
117     */
118    protected MetadataAwareAmetysObject getAmetysObject() throws ProcessingException
119    {
120        MetadataAwareAmetysObject object = null;
121        
122        Request request = ObjectModelHelper.getRequest(objectModel);
123        String objectPath = parameters.getParameter("objectPath", request.getParameter("objectPath"));
124        String objectId = parameters.getParameter("objectId", request.getParameter("objectId"));
125        // Legacy parameter name.
126        if (StringUtils.isBlank(objectId))
127        {
128            objectId = parameters.getParameter("contentId", request.getParameter("contentId"));
129        }
130        
131        if (StringUtils.isNotBlank(objectId))
132        {
133            object = _resolver.resolveById(objectId);
134        }
135        else if (StringUtils.isNotBlank(objectPath))
136        {
137            objectPath = objectPath.replaceAll("%3A", ":");
138            object = _resolver.resolveByPath(objectPath);
139        }
140        else
141        {
142            object = (Content) request.getAttribute(Content.class.getName());
143        }
144        
145        if (object == null)
146        {
147            throw new ProcessingException("The object ID parameter is mandatory for reading binary metadata.");
148        }
149        
150        String revision = parameters.getParameter("contentVersion", null);
151        if (StringUtils.isNotEmpty(revision) && object instanceof VersionableAmetysObject)
152        {
153            ((VersionableAmetysObject) object).switchToRevision(revision);
154        }
155        
156        return object;
157    }
158    
159    @Override
160    protected InputStream getInputStream()
161    {
162        return _binary.getInputStream();
163    }
164    
165    @Override
166    protected String getFilename()
167    {
168        return _binary.getFilename();
169    }
170    
171    @Override
172    protected String getEncodedFilename()
173    {
174        return null;
175    }
176    
177    @Override
178    protected long getLength()
179    {
180        return _binary.getLength();
181    }
182
183    @Override
184    public Serializable getKey()
185    {
186        return _ametysObject.getId() + ";" + _path + getKeySuffix();
187    }
188
189    @Override
190    public SourceValidity getValidity()
191    {
192        return new TimeStampValidity(getLastModified());
193    }
194    
195    @Override
196    public long getLastModified()
197    {
198        if (_binary != null)
199        {
200            return _binary.getLastModified().getTime();
201        }
202        
203        return super.getLastModified();
204    }
205    
206    @Override
207    public String getMimeType()
208    {
209        if (_binary != null)
210        {
211            return _binary.getMimeType();
212        }
213
214        return super.getMimeType();
215    }
216
217    @Override
218    public void recycle()
219    {
220        super.recycle();
221        
222        _binary = null;
223        _ametysObject = null;
224    }
225}