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 _context = new HashMap<String, Object>();
072 }
073
074 @Override
075 public Object get(String key) {
076 return _context.get(key);
077 }
078
079 @Override
080 public String[] getKeys() {
081 Set<String> keys = _context.keySet();
082
083 return keys.toArray(new String[keys.size()]);
084 }
085
086 @Override
087 public void prepare(HttpServletRequest request) {
088 _templateContextHelper.prepare(this, request);
089 }
090
091 @Override
092 public void processTemplate(Writer writer) throws TemplateException {
093 TransformerFactory transformerFactory =
094 TransformerFactory.newInstance();
095
096 try {
097 transformerFactory.setFeature(
098 XMLConstants.FEATURE_SECURE_PROCESSING,
099 PropsValues.XSL_TEMPLATE_SECURE_PROCESSING_ENABLED);
100 }
101 catch (TransformerConfigurationException tce) {
102 }
103
104 String languageId = null;
105
106 XSLURIResolver xslURIResolver =
107 _xslTemplateResource.getXSLURIResolver();
108
109 if (xslURIResolver != null) {
110 languageId = xslURIResolver.getLanguageId();
111 }
112
113 Locale locale = LocaleUtil.fromLanguageId(languageId);
114
115 XSLErrorListener xslErrorListener = new XSLErrorListener(locale);
116
117 transformerFactory.setErrorListener(xslErrorListener);
118
119 transformerFactory.setURIResolver(xslURIResolver);
120
121 StreamSource xmlSource = new StreamSource(
122 _xslTemplateResource.getXMLReader());
123
124 Transformer transformer = null;
125
126 if (_errorTemplateResource == null) {
127 try {
128 transformer = _getTransformer(
129 transformerFactory, _xslTemplateResource);
130
131 transformer.transform(xmlSource, new StreamResult(writer));
132
133 return;
134 }
135 catch (Exception e) {
136 throw new TemplateException(
137 "Unable to process XSL template " +
138 _xslTemplateResource.getTemplateId(),
139 e);
140 }
141 }
142
143 try {
144 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
145
146 transformer = _getTransformer(
147 transformerFactory, _xslTemplateResource);
148
149 transformer.setParameter(
150 TemplateConstants.WRITER, unsyncStringWriter);
151
152 transformer.transform(
153 xmlSource, new StreamResult(unsyncStringWriter));
154
155 StringBundler sb = unsyncStringWriter.getStringBundler();
156
157 sb.writeTo(writer);
158 }
159 catch (Exception e1) {
160 Transformer errorTransformer = _getTransformer(
161 transformerFactory, _errorTemplateResource);
162
163 errorTransformer.setParameter(TemplateConstants.WRITER, writer);
164 errorTransformer.setParameter(
165 "exception", xslErrorListener.getMessageAndLocation());
166
167 if (_errorTemplateResource instanceof StringTemplateResource) {
168 StringTemplateResource stringTemplateResource =
169 (StringTemplateResource)_errorTemplateResource;
170
171 errorTransformer.setParameter(
172 "script", stringTemplateResource.getContent());
173 }
174
175 if (xslErrorListener.getLocation() != null) {
176 errorTransformer.setParameter(
177 "column", new Integer(xslErrorListener.getColumnNumber()));
178 errorTransformer.setParameter(
179 "line", new Integer(xslErrorListener.getLineNumber()));
180 }
181
182 try {
183 errorTransformer.transform(xmlSource, new StreamResult(writer));
184 }
185 catch (Exception e2) {
186 throw new TemplateException(
187 "Unable to process XSL template " +
188 _errorTemplateResource.getTemplateId(),
189 e2);
190 }
191 }
192 }
193
194 @Override
195 public void put(String key, Object value) {
196 if (value == null) {
197 return;
198 }
199
200 _context.put(key, value);
201 }
202
203 private Transformer _getTransformer(
204 TransformerFactory transformerFactory,
205 TemplateResource templateResource)
206 throws TemplateException {
207
208 try {
209 StreamSource scriptSource = new StreamSource(
210 templateResource.getReader());
211
212 Transformer transformer = AccessController.doPrivileged(
213 new TransformerPrivilegedExceptionAction(
214 transformerFactory, scriptSource));
215
216 for (Map.Entry<String, Object> entry : _context.entrySet()) {
217 transformer.setParameter(entry.getKey(), entry.getValue());
218 }
219
220 return transformer;
221 }
222 catch (PrivilegedActionException pae) {
223 throw new TemplateException(
224 "Unable to get Transformer for template " +
225 templateResource.getTemplateId(),
226 pae.getException());
227 }
228 catch (Exception e) {
229 throw new TemplateException(
230 "Unable to get Transformer for template " +
231 templateResource.getTemplateId(),
232 e);
233 }
234 }
235
236 private Map<String, Object> _context;
237 private TemplateResource _errorTemplateResource;
238 private TemplateContextHelper _templateContextHelper;
239 private XSLTemplateResource _xslTemplateResource;
240
241 private class TransformerPrivilegedExceptionAction
242 implements PrivilegedExceptionAction<Transformer> {
243
244 public TransformerPrivilegedExceptionAction(
245 TransformerFactory transformerFactory, StreamSource scriptSource) {
246
247 _transformerFactory = transformerFactory;
248 _scriptSource = scriptSource;
249 }
250
251 @Override
252 public Transformer run() throws Exception {
253 return _transformerFactory.newTransformer(_scriptSource);
254 }
255
256 private StreamSource _scriptSource;
257 private TransformerFactory _transformerFactory;
258
259 }
260
261 }