001/*
002 *  Copyright 2011 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 */
016
017package org.ametys.cms.transformation;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.util.Date;
022import java.util.HashMap;
023import java.util.Map;
024
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.commons.io.IOUtils;
029import org.apache.excalibur.source.Source;
030import org.apache.excalibur.source.SourceResolver;
031import org.apache.excalibur.xml.sax.SAXParser;
032import org.xml.sax.ContentHandler;
033import org.xml.sax.InputSource;
034import org.xml.sax.SAXException;
035
036import org.ametys.core.util.IgnoreRootHandler;
037import org.ametys.plugins.repository.AmetysRepositoryException;
038import org.ametys.plugins.repository.metadata.ModifiableRichText;
039import org.ametys.plugins.repository.metadata.RichText;
040
041/**
042 * Abstract class for {@link RichTextTransformer}s relying on Cocoon pipelines to actually transform HTML to RichText back and forth.
043 */
044public abstract class AbstractRichTextTransformer implements RichTextTransformer, Serviceable
045{
046    private SourceResolver _sourceResolver;
047    private ServiceManager _manager;
048    
049    public void service(ServiceManager manager) throws ServiceException
050    {
051        _manager = manager;
052        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
053    }
054    
055    @SuppressWarnings("unchecked")
056    public void transform(String source, ModifiableRichText dest) throws AmetysRepositoryException, IOException
057    {
058        Source xmlSource = null;
059        
060        try 
061        {
062            Map parameters = new HashMap();
063            parameters.put("source", source);
064            parameters.put("richText", dest);
065
066            xmlSource = _sourceResolver.resolveURI(_getSourceUriForHTML2RichText(), null, parameters);
067            
068            try (InputStream is = xmlSource.getInputStream())
069            {
070                dest.setMimeType("application/xml");
071                dest.setLastModified(new Date());
072                dest.setInputStream(is);
073            }
074        }
075        finally
076        {
077            _sourceResolver.release(xmlSource);
078        }
079    }
080    
081    /**
082     * Returns the internal {@link Source} URI used to process the HTML editor content. 
083     * @return the internal {@link Source} URI used to process the HTML editor content. 
084     */
085    protected abstract String _getSourceUriForHTML2RichText();
086    
087    @Override
088    public void transformForEditing(ModifiableRichText source, StringBuilder dest) throws AmetysRepositoryException, IOException
089    {
090        Source textSource = null;
091        
092        try (InputStream is = source.getInputStream())
093        {
094            Map<String, Object> parameters = new HashMap<>();
095            parameters.put("source", is);
096            
097            textSource = _sourceResolver.resolveURI(_getSourceUriForRichText2HTML(), null, parameters);
098            
099            try (InputStream textSourceIs = textSource.getInputStream())
100            {
101                dest.append(IOUtils.toString(textSourceIs, "UTF-8"));
102            }
103        }
104        finally
105        {
106            _sourceResolver.release(textSource);
107        }
108    }
109    
110    /**
111     * Returns the internal {@link Source} URI used to process the RichText's InputStream. 
112     * @return the internal {@link Source} URI used to process the RichText's InputStream. 
113     */
114    protected abstract String _getSourceUriForRichText2HTML();
115
116    @Override
117    public void transformForRendering(RichText source, ContentHandler handler) throws AmetysRepositoryException, SAXException, IOException
118    {
119        SAXParser saxParser = null;
120        
121        try
122        {
123            saxParser = (SAXParser) _manager.lookup(SAXParser.ROLE);
124            
125            try (InputStream is = source.getInputStream())
126            {
127                saxParser.parse(new InputSource(is), new IgnoreRootHandler(handler));
128            }
129        }
130        catch (ServiceException e)
131        {
132            throw new AmetysRepositoryException("Unable to get SAX parser", e);
133        }
134        finally
135        {
136            _manager.release(saxParser);
137        }
138    }
139}