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