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.workspaces.repository.jcr;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.util.Map;
021
022import javax.jcr.Node;
023import javax.jcr.Property;
024import javax.jcr.RepositoryException;
025import javax.jcr.Session;
026
027import org.apache.avalon.framework.parameters.Parameters;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.cocoon.ProcessingException;
031import org.apache.cocoon.environment.ObjectModelHelper;
032import org.apache.cocoon.environment.Response;
033import org.apache.cocoon.environment.SourceResolver;
034import org.apache.cocoon.reading.Reader;
035import org.apache.cocoon.reading.ServiceableReader;
036import org.apache.commons.io.IOUtils;
037import org.xml.sax.SAXException;
038
039import org.ametys.plugins.repositoryapp.RepositoryProvider;
040
041/**
042 * {@link Reader} for exposing a binary property from a JCR repository.<br>
043 * Mime type can be forced by using parameter <code>mime-type</code>.
044 */
045public class BinaryPropertyReader extends ServiceableReader
046{
047    
048    /** The repository provider. */
049    protected RepositoryProvider _repositoryProvider;
050    
051    private Node _node;
052    private Property _property;
053    
054    @Override
055    public void service(ServiceManager serviceManager) throws ServiceException
056    {
057        super.service(serviceManager);
058        _repositoryProvider = (RepositoryProvider) serviceManager.lookup(RepositoryProvider.ROLE);
059    }
060    
061    @Override
062    public void setup(SourceResolver res, Map objModel, String src, Parameters par) throws ProcessingException, SAXException, IOException
063    {
064        super.setup(res, objModel, src, par);
065        
066        Session session = null;
067        String workspaceName = null;
068        
069        try
070        {
071            workspaceName = parameters.getParameter("workspace");
072            
073            session = _repositoryProvider.getSession(workspaceName);
074        }
075        catch (Exception e)
076        {
077            throw new ProcessingException("Unable to retrieve repository", e);
078        }
079        
080        try
081        {
082            String path = par.getParameter("path", "");
083            String relPath = RepositoryDao.removeLeadingSlash(path);
084            
085            _node = session.getRootNode().getNode(relPath);
086            
087            String name = par.getParameter("property", null);
088            _property = _node.getProperty(name);
089        }
090        catch (RepositoryException e)
091        {
092            throw new ProcessingException(e);
093        }
094    }
095    
096    @Override
097    public String getMimeType()
098    {
099        try
100        {
101            if (_node.hasProperty("jcr:mimeType"))
102            {
103                return _node.getProperty("jcr:mimeType").getString();
104            }
105        }
106        catch (RepositoryException e)
107        {
108            // Nothing
109        }
110        
111        return "application/unknown";
112    }
113    
114    private String _getName () throws RepositoryException
115    {
116        if ("nt:resource".equals(_node.getPrimaryNodeType().getName()))
117        {
118            return _node.getParent().getName();
119        }
120        
121        return _property.getName();
122    }
123
124    @SuppressWarnings("deprecation")
125    public void generate() throws IOException, SAXException, ProcessingException
126    {
127        String path = null;
128        try
129        {
130            String name = _getName ();
131            name = name.replaceAll("\\\\", "\\\\\\\\");
132            name = name.replaceAll("\\\"", "\\\\\\\"");
133            
134            path = _property.getPath();
135            
136            Response response = ObjectModelHelper.getResponse(objectModel);
137            
138            response.setHeader("Content-Length", Long.toString(_property.getLength()));
139            response.setHeader("Content-Disposition", "attachment; filename=\"" + name + "\"");
140            
141            try (InputStream is = _property.getBinary().getStream())
142            {
143                IOUtils.copy(is, out);
144            }
145        }
146        catch (Exception e)
147        {
148            throw new ProcessingException("Unable to download binary property of path " + path, e);
149        }
150        finally
151        {
152            IOUtils.closeQuietly(out);
153        }
154    }
155}