1 /*
2 * Copyright (c) 2002-2025, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 package fr.paris.lutece.portal.service.html;
35
36 import java.io.ByteArrayInputStream;
37 import java.io.StringReader;
38 import java.util.Map;
39 import java.util.Properties;
40
41 import javax.xml.transform.Source;
42 import javax.xml.transform.stream.StreamSource;
43
44 import org.apache.logging.log4j.LogManager;
45 import org.apache.logging.log4j.Logger;
46
47 import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
48 import fr.paris.lutece.portal.service.util.AppLogService;
49 import fr.paris.lutece.util.UniqueIDGenerator;
50 import fr.paris.lutece.util.xml.XmlTransformer;
51
52 /**
53 * This class provides methods to transform XML documents using XSLT.
54 */
55 public final class XmlTransformerService
56 {
57 private static final String XSLSOURCE_STYLE_PREFIX_ID = UniqueIDGenerator.getNewId( );
58 private static final String LOGGER_XML_CONTENT = "lutece.debug.xmlContent";
59 private static final String ERROR_MESSAGE_XSL_TRANSFORMATION = "An error occurred during XSL transformation. The requested operation was blocked for security reasons.";
60 private static final Logger _log = LogManager.getLogger( LOGGER_XML_CONTENT );
61
62 /**
63 * This method performs XSL transformation with cache.
64 *
65 * @param strXml
66 * The XML document content
67 * @param xslSource
68 * The XSL source
69 * @param params
70 * Parameters that can be used by the XSL StyleSheet
71 * @return the output html
72 */
73 public String transformBySourceWithXslCache( String strXml, StyleSheet xslSource, Map<String, String> params )
74 {
75 return transformBySourceWithXslCache( strXml, xslSource.getSource( ), XSLSOURCE_STYLE_PREFIX_ID + xslSource.getId( ), params, null );
76 }
77
78 /**
79 * This method performs XSL transformation with cache.
80 *
81 * @param strXml
82 * The XML document content
83 * @param xslSource
84 * The XSL source
85 * @param params
86 * Parameters that can be used by the XSL StyleSheet
87 * @param outputProperties
88 * Properties to use for the XSL transform. Will overload the XSL output definition.
89 * @return the output html
90 */
91 public String transformBySourceWithXslCache( String strXml, StyleSheet xslSource, Map<String, String> params, Properties outputProperties )
92 {
93 return transformBySourceWithXslCache( strXml, xslSource.getSource( ), XSLSOURCE_STYLE_PREFIX_ID + xslSource.getId( ), params, outputProperties );
94 }
95
96 /**
97 * This method performs XSL transformation with cache.
98 *
99 * @param strXml
100 * The XML document content
101 * @param baSource
102 * The XSL source
103 * @param strStyleSheetId
104 * The StyleSheet Id
105 * @param params
106 * Parameters that can be used by the XSL StyleSheet
107 * @return The output document
108 */
109 public String transformBySourceWithXslCache( String strXml, byte [ ] baSource, String strStyleSheetId, Map<String, String> params )
110 {
111 return transformBySourceWithXslCache( strXml, baSource, strStyleSheetId, params, null );
112 }
113
114 /**
115 * This method performs XSL transformation with cache.
116 *
117 * @param strXml
118 * The XML document content
119 * @param baSource
120 * The XSL source
121 * @param strStyleSheetId
122 * The StyleSheet Id
123 * @param params
124 * Parameters that can be used by the XSL StyleSheet
125 * @param outputProperties
126 * Properties to use for the XSL transform. Will overload the XSL output definition.
127 * @return The output document
128 */
129 public String transformBySourceWithXslCache( String strXml, byte [ ] baSource, String strStyleSheetId, Map<String, String> params,
130 Properties outputProperties )
131 {
132 Source xslSource = new StreamSource( new ByteArrayInputStream( baSource ) );
133
134 return transformBySourceWithXslCache( strXml, xslSource, strStyleSheetId, params, outputProperties );
135 }
136
137 /**
138 * This method performs XSL transformation with cache.
139 *
140 * @param strXml
141 * The XML document content
142 * @param sourceStyleSheet
143 * The XSL source
144 * @param strStyleSheetId
145 * The StyleSheet Id
146 * @param params
147 * Parameters that can be used by the XSL StyleSheet
148 * @param outputProperties
149 * the output parameter
150 * @return The output document
151 */
152 public String transformBySourceWithXslCache( String strXml, Source sourceStyleSheet, String strStyleSheetId, Map<String, String> params,
153 Properties outputProperties )
154 {
155 StringReader srInputXml = new StringReader( strXml );
156 StreamSource sourceDocument = new StreamSource( srInputXml );
157 String strContent = null;
158 XmlTransformerr.html#XmlTransformer">XmlTransformer xmlTransformer = new XmlTransformer( );
159
160 try
161 {
162 _log.debug( strXml );
163 strContent = xmlTransformer.transform( sourceDocument, sourceStyleSheet, strStyleSheetId, params, outputProperties );
164 }
165 catch( Exception e )
166 {
167 strContent = ERROR_MESSAGE_XSL_TRANSFORMATION;
168 AppLogService.error( "XSL transformation error for stylesheet {}", strStyleSheetId, e );
169 }
170
171 return strContent;
172 }
173
174 /**
175 * This method performs XSL transformation with cache.
176 *
177 * @param sourceXml
178 * The XML document content
179 * @param sourceStyleSheet
180 * The XSL source
181 * @param strStyleSheetId
182 * The StyleSheet Id
183 * @param params
184 * Parameters that can be used by the XSL StyleSheet
185 * @param outputProperties
186 * the output parameter
187 * @return The output document
188 */
189 public String transformBySourceWithXslCache( Source sourceXml, Source sourceStyleSheet, String strStyleSheetId, Map<String, String> params,
190 Properties outputProperties )
191 {
192 String strContent = null;
193 XmlTransformerr.html#XmlTransformer">XmlTransformer xmlTransformer = new XmlTransformer( );
194
195 try
196 {
197 strContent = xmlTransformer.transform( sourceXml, sourceStyleSheet, strStyleSheetId, params, outputProperties );
198 }
199 catch( Exception e )
200 {
201 strContent = ERROR_MESSAGE_XSL_TRANSFORMATION;
202 AppLogService.error( "XSL transformation error for stylesheet {}", strStyleSheetId, e );
203 }
204
205 return strContent;
206 }
207
208 /**
209 * This method clean XSL transformer cache
210 */
211 public static void clearXslCache( )
212 {
213 XmlTransformer.cleanTransformerList( );
214 }
215 }