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