001
014
015 package com.liferay.portal.xsl;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
018 import com.liferay.portal.kernel.template.StringTemplateResource;
019 import com.liferay.portal.kernel.template.Template;
020 import com.liferay.portal.kernel.template.TemplateConstants;
021 import com.liferay.portal.kernel.template.TemplateException;
022 import com.liferay.portal.kernel.template.TemplateResource;
023 import com.liferay.portal.kernel.util.LocaleUtil;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.template.TemplateContextHelper;
026 import com.liferay.portal.util.PropsValues;
027
028 import java.io.Writer;
029
030 import java.security.AccessController;
031 import java.security.PrivilegedActionException;
032 import java.security.PrivilegedExceptionAction;
033
034 import java.util.HashMap;
035 import java.util.Locale;
036 import java.util.Map;
037 import java.util.Set;
038
039 import javax.servlet.http.HttpServletRequest;
040
041 import javax.xml.XMLConstants;
042 import javax.xml.transform.Transformer;
043 import javax.xml.transform.TransformerConfigurationException;
044 import javax.xml.transform.TransformerFactory;
045 import javax.xml.transform.stream.StreamResult;
046 import javax.xml.transform.stream.StreamSource;
047
048
051 public class XSLTemplate implements Template {
052
053 public XSLTemplate(
054 XSLTemplateResource xslTemplateResource,
055 TemplateResource errorTemplateResource,
056 TemplateContextHelper templateContextHelper) {
057
058 if (xslTemplateResource == null) {
059 throw new IllegalArgumentException("XSL template resource is null");
060 }
061
062 if (templateContextHelper == null) {
063 throw new IllegalArgumentException(
064 "Template context helper is null");
065 }
066
067 _xslTemplateResource = xslTemplateResource;
068 _errorTemplateResource = errorTemplateResource;
069 _templateContextHelper = templateContextHelper;
070
071 _transformerFactory = TransformerFactory.newInstance();
072
073 try {
074 _transformerFactory.setFeature(
075 XMLConstants.FEATURE_SECURE_PROCESSING,
076 PropsValues.XSL_TEMPLATE_SECURE_PROCESSING_ENABLED);
077 }
078 catch (TransformerConfigurationException tce) {
079 }
080
081 _context = new HashMap<String, Object>();
082 }
083
084 @Override
085 public void doProcessTemplate(Writer writer) throws Exception {
086 String languageId = null;
087
088 XSLURIResolver xslURIResolver =
089 _xslTemplateResource.getXSLURIResolver();
090
091 if (xslURIResolver != null) {
092 languageId = xslURIResolver.getLanguageId();
093 }
094
095 Locale locale = LocaleUtil.fromLanguageId(languageId);
096
097 XSLErrorListener xslErrorListener = new XSLErrorListener(locale);
098
099 _transformerFactory.setErrorListener(xslErrorListener);
100
101 _transformerFactory.setURIResolver(xslURIResolver);
102
103 _xmlStreamSource = new StreamSource(
104 _xslTemplateResource.getXMLReader());
105
106 Transformer transformer = null;
107
108 if (_errorTemplateResource == null) {
109 try {
110 transformer = _getTransformer(
111 _transformerFactory, _xslTemplateResource);
112
113 transformer.transform(
114 _xmlStreamSource, new StreamResult(writer));
115
116 return;
117 }
118 catch (Exception e) {
119 throw new TemplateException(
120 "Unable to process XSL template " +
121 _xslTemplateResource.getTemplateId(),
122 e);
123 }
124 }
125
126 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
127
128 transformer = _getTransformer(
129 _transformerFactory, _xslTemplateResource);
130
131 transformer.setParameter(TemplateConstants.WRITER, unsyncStringWriter);
132
133 transformer.transform(
134 _xmlStreamSource, new StreamResult(unsyncStringWriter));
135
136 StringBundler sb = unsyncStringWriter.getStringBundler();
137
138 sb.writeTo(writer);
139 }
140
141 @Override
142 public Object get(String key) {
143 return _context.get(key);
144 }
145
146 @Override
147 public String[] getKeys() {
148 Set<String> keys = _context.keySet();
149
150 return keys.toArray(new String[keys.size()]);
151 }
152
153 @Override
154 public void prepare(HttpServletRequest request) {
155 _templateContextHelper.prepare(this, request);
156 }
157
158 @Override
159 public void processTemplate(Writer writer) throws TemplateException {
160 try {
161 doProcessTemplate(writer);
162 }
163 catch (Exception e1) {
164 Transformer errorTransformer = _getTransformer(
165 _transformerFactory, _errorTemplateResource);
166
167 errorTransformer.setParameter(TemplateConstants.WRITER, writer);
168
169 XSLErrorListener xslErrorListener =
170 (XSLErrorListener)_transformerFactory.getErrorListener();
171
172 errorTransformer.setParameter(
173 "exception", xslErrorListener.getMessageAndLocation());
174
175 if (_errorTemplateResource instanceof StringTemplateResource) {
176 StringTemplateResource stringTemplateResource =
177 (StringTemplateResource)_errorTemplateResource;
178
179 errorTransformer.setParameter(
180 "script", stringTemplateResource.getContent());
181 }
182
183 if (xslErrorListener.getLocation() != null) {
184 errorTransformer.setParameter(
185 "column", new Integer(xslErrorListener.getColumnNumber()));
186 errorTransformer.setParameter(
187 "line", new Integer(xslErrorListener.getLineNumber()));
188 }
189
190 try {
191 errorTransformer.transform(
192 _xmlStreamSource, new StreamResult(writer));
193 }
194 catch (Exception e2) {
195 throw new TemplateException(
196 "Unable to process XSL template " +
197 _errorTemplateResource.getTemplateId(),
198 e2);
199 }
200 }
201 }
202
203 @Override
204 public void put(String key, Object value) {
205 if (value == null) {
206 return;
207 }
208
209 _context.put(key, value);
210 }
211
212 private Transformer _getTransformer(
213 TransformerFactory transformerFactory,
214 TemplateResource templateResource)
215 throws TemplateException {
216
217 try {
218 StreamSource scriptSource = new StreamSource(
219 templateResource.getReader());
220
221 Transformer transformer = AccessController.doPrivileged(
222 new TransformerPrivilegedExceptionAction(
223 transformerFactory, scriptSource));
224
225 for (Map.Entry<String, Object> entry : _context.entrySet()) {
226 transformer.setParameter(entry.getKey(), entry.getValue());
227 }
228
229 return transformer;
230 }
231 catch (PrivilegedActionException pae) {
232 throw new TemplateException(
233 "Unable to get Transformer for template " +
234 templateResource.getTemplateId(),
235 pae.getException());
236 }
237 catch (Exception e) {
238 throw new TemplateException(
239 "Unable to get Transformer for template " +
240 templateResource.getTemplateId(),
241 e);
242 }
243 }
244
245 private final Map<String, Object> _context;
246 private TemplateResource _errorTemplateResource;
247 private final TemplateContextHelper _templateContextHelper;
248 private TransformerFactory _transformerFactory;
249 private StreamSource _xmlStreamSource;
250 private final XSLTemplateResource _xslTemplateResource;
251
252 private class TransformerPrivilegedExceptionAction
253 implements PrivilegedExceptionAction<Transformer> {
254
255 public TransformerPrivilegedExceptionAction(
256 TransformerFactory transformerFactory, StreamSource scriptSource) {
257
258 _transformerFactory = transformerFactory;
259 _scriptSource = scriptSource;
260 }
261
262 @Override
263 public Transformer run() throws Exception {
264 return _transformerFactory.newTransformer(_scriptSource);
265 }
266
267 private final StreamSource _scriptSource;
268 private TransformerFactory _transformerFactory;
269
270 }
271
272 }