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.time.ZonedDateTime; 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.cms.data.RichText; 037import org.ametys.core.util.IgnoreRootHandler; 038import org.ametys.plugins.repository.AmetysRepositoryException; 039import org.ametys.runtime.model.type.DataContext; 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 public void transform(String source, RichText dest) throws AmetysRepositoryException, IOException 056 { 057 Source xmlSource = null; 058 059 try 060 { 061 Map<String, Object> parameters = new HashMap<>(); 062 parameters.put("source", source); 063 parameters.put("richText", dest); 064 065 xmlSource = _sourceResolver.resolveURI(_getSourceUriForHTML2RichText(), null, parameters); 066 067 try (InputStream is = xmlSource.getInputStream()) 068 { 069 dest.setMimeType("application/xml"); 070 dest.setLastModificationDate(ZonedDateTime.now()); 071 dest.setInputStream(is); 072 } 073 } 074 finally 075 { 076 _sourceResolver.release(xmlSource); 077 } 078 } 079 080 /** 081 * Returns the internal {@link Source} URI used to process the HTML editor content. 082 * @return the internal {@link Source} URI used to process the HTML editor content. 083 */ 084 protected abstract String _getSourceUriForHTML2RichText(); 085 086 public void transformForEditing(RichText source, DataContext dataContext, StringBuilder dest) throws AmetysRepositoryException, IOException 087 { 088 Source textSource = null; 089 090 try (InputStream is = source.getInputStream()) 091 { 092 Map<String, Object> parameters = new HashMap<>(); 093 parameters.put("source", is); 094 parameters.put("dataContext", dataContext); 095 096 textSource = _sourceResolver.resolveURI(_getSourceUriForRichText2HTML(), null, parameters); 097 098 try (InputStream textSourceIs = textSource.getInputStream()) 099 { 100 dest.append(IOUtils.toString(textSourceIs, "UTF-8")); 101 } 102 } 103 finally 104 { 105 _sourceResolver.release(textSource); 106 } 107 } 108 109 /** 110 * Returns the internal {@link Source} URI used to process the RichText's InputStream. 111 * @return the internal {@link Source} URI used to process the RichText's InputStream. 112 */ 113 protected abstract String _getSourceUriForRichText2HTML(); 114 115 public void transformForRendering(RichText source, ContentHandler handler) throws AmetysRepositoryException, SAXException, IOException 116 { 117 SAXParser saxParser = null; 118 119 try 120 { 121 saxParser = (SAXParser) _manager.lookup(SAXParser.ROLE); 122 123 try (InputStream is = source.getInputStream()) 124 { 125 saxParser.parse(new InputSource(is), new IgnoreRootHandler(handler)); 126 } 127 } 128 catch (ServiceException e) 129 { 130 throw new AmetysRepositoryException("Unable to get SAX parser", e); 131 } 132 finally 133 { 134 _manager.release(saxParser); 135 } 136 } 137}