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.apache.jackrabbit.JcrConstants;
038import org.xml.sax.SAXException;
039
040import org.ametys.plugins.repositoryapp.RepositoryProvider;
041
042/**
043 * {@link Reader} for exposing a binary property from a JCR repository.<br>
044 * Mime type can be forced by using parameter <code>mime-type</code>.
045 */
046public class BinaryPropertyReader extends ServiceableReader
047{
048    
049    /** The repository provider. */
050    protected RepositoryProvider _repositoryProvider;
051    
052    private Node _node;
053    private Property _property;
054    
055    @Override
056    public void service(ServiceManager serviceManager) throws ServiceException
057    {
058        super.service(serviceManager);
059        _repositoryProvider = (RepositoryProvider) serviceManager.lookup(RepositoryProvider.ROLE);
060    }
061    
062    @Override
063    public void setup(SourceResolver res, Map objModel, String src, Parameters par) throws ProcessingException, SAXException, IOException
064    {
065        super.setup(res, objModel, src, par);
066        
067        Session session = null;
068        String workspaceName = null;
069        
070        try
071        {
072            workspaceName = parameters.getParameter("workspace");
073            
074            session = _repositoryProvider.getSession(workspaceName);
075        }
076        catch (Exception e)
077        {
078            throw new ProcessingException("Unable to retrieve repository", e);
079        }
080        
081        try
082        {
083            String path = par.getParameter("path", "");
084            String relPath = RepositoryDao.removeLeadingSlash(path);
085            
086            _node = session.getRootNode().getNode(relPath);
087            
088            String name = par.getParameter("property", null);
089            _property = _node.getProperty(name);
090        }
091        catch (RepositoryException e)
092        {
093            throw new ProcessingException(e);
094        }
095    }
096    
097    @Override
098    public String getMimeType()
099    {
100        try
101        {
102            if (_node.hasProperty(JcrConstants.JCR_MIMETYPE))
103            {
104                return _node.getProperty(JcrConstants.JCR_MIMETYPE).getString();
105            }
106        }
107        catch (RepositoryException e)
108        {
109            // Nothing
110        }
111        
112        return "application/unknown";
113    }
114    
115    private String _getName () throws RepositoryException
116    {
117        if (JcrConstants.NT_RESOURCE.equals(_node.getPrimaryNodeType().getName()))
118        {
119            return _node.getParent().getName();
120        }
121        
122        return _property.getName();
123    }
124
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}