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