1
22
23 package com.liferay.portlet.journal.util;
24
25 import com.liferay.portal.kernel.util.GetterUtil;
26 import com.liferay.portal.kernel.util.HtmlUtil;
27 import com.liferay.portal.kernel.util.LocaleUtil;
28 import com.liferay.portal.kernel.util.StringPool;
29 import com.liferay.portal.kernel.util.StringUtil;
30 import com.liferay.portal.kernel.velocity.VelocityContext;
31 import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
32 import com.liferay.portal.kernel.xml.Document;
33 import com.liferay.portal.kernel.xml.DocumentException;
34 import com.liferay.portal.kernel.xml.Element;
35 import com.liferay.portal.kernel.xml.Node;
36 import com.liferay.portal.kernel.xml.SAXReaderUtil;
37 import com.liferay.portal.model.Company;
38 import com.liferay.portal.security.permission.PermissionThreadLocal;
39 import com.liferay.portal.service.CompanyLocalServiceUtil;
40 import com.liferay.portal.util.ContentUtil;
41 import com.liferay.portal.util.PropsValues;
42 import com.liferay.portal.velocity.VelocityResourceListener;
43 import com.liferay.portlet.journal.TransformException;
44 import com.liferay.util.PwdGenerator;
45 import com.liferay.util.xml.CDATAUtil;
46
47 import java.io.IOException;
48 import java.io.StringWriter;
49
50 import java.util.ArrayList;
51 import java.util.HashMap;
52 import java.util.List;
53 import java.util.Map;
54
55 import org.apache.velocity.exception.ParseErrorException;
56 import org.apache.velocity.exception.VelocityException;
57
58
66 public class JournalVmUtil {
67
68 public static List<TemplateNode> extractDynamicContents(Element parent)
69 throws TransformException {
70
71 List<TemplateNode> nodes = new ArrayList<TemplateNode>();
72
73 Map<String, TemplateNode> prototypeNodes =
74 new HashMap<String, TemplateNode>();
75
76 for (Element el : parent.elements("dynamic-element")) {
77 Element content = el.element("dynamic-content");
78
79 if (content == null) {
80 throw new TransformException(
81 "Element missing \"dynamic-content\"");
82 }
83
84 String name = el.attributeValue("name", "");
85
86 if (name.length() == 0) {
87 throw new TransformException(
88 "Element missing \"name\" attribute");
89 }
90
91 String type = el.attributeValue("type", "");
92
93 TemplateNode node = new TemplateNode(
94 name, CDATAUtil.strip(content.getText()), type);
95
96 if (el.element("dynamic-element") != null) {
97 node.appendChildren(extractDynamicContents(el));
98 }
99 else if (content.element("option") != null) {
100 for (Element option : content.elements("option")) {
101 node.appendOption(CDATAUtil.strip(option.getText()));
102 }
103 }
104
105 TemplateNode prototypeNode = prototypeNodes.get(name);
106
107 if (prototypeNode == null) {
108 prototypeNode = node;
109
110 prototypeNodes.put(name, prototypeNode);
111
112 nodes.add(node);
113 }
114
115 prototypeNode.appendSibling(node);
116 }
117
118 return nodes;
119 }
120
121 public static String transform(
122 Map<String, String> tokens, String viewMode, String languageId,
123 String xml, String script)
124 throws TransformException {
125
126 StringWriter output = new StringWriter();
127
128 boolean load = false;
129
130 try {
131 VelocityContext velocityContext =
132 VelocityEngineUtil.getWrappedRestrictedToolsContext();
133
134 Document doc = SAXReaderUtil.read(xml);
135
136 Element root = doc.getRootElement();
137
138 List<TemplateNode> nodes = extractDynamicContents(root);
139
140 for (TemplateNode node : nodes) {
141 velocityContext.put(node.getName(), node);
142 }
143
144 velocityContext.put("xmlRequest", root.element("request").asXML());
145 velocityContext.put(
146 "request", insertRequestVariables(root.element("request")));
147
148 long companyId = GetterUtil.getLong(tokens.get("company_id"));
149 Company company = CompanyLocalServiceUtil.getCompanyById(companyId);
150 long groupId = GetterUtil.getLong(tokens.get("group_id"));
151 String templateId = tokens.get("template_id");
152 String journalTemplatesPath =
153 VelocityResourceListener.JOURNAL_SEPARATOR + StringPool.SLASH +
154 companyId + StringPool.SLASH + groupId;
155 String randomNamespace =
156 PwdGenerator.getPassword(PwdGenerator.KEY3, 4) +
157 StringPool.UNDERLINE;
158
159 velocityContext.put("company", company);
160 velocityContext.put("companyId", String.valueOf(companyId));
161 velocityContext.put("groupId", String.valueOf(groupId));
162 velocityContext.put("journalTemplatesPath", journalTemplatesPath);
163 velocityContext.put("viewMode", viewMode);
164 velocityContext.put(
165 "locale", LocaleUtil.fromLanguageId(languageId));
166 velocityContext.put(
167 "permissionChecker",
168 PermissionThreadLocal.getPermissionChecker());
169 velocityContext.put("randomNamespace", randomNamespace);
170
171 script = injectEditInPlace(xml, script);
172
173 try {
174 String velocityTemplateId = companyId + groupId + templateId;
175
176 load = VelocityEngineUtil.mergeTemplate(
177 velocityTemplateId, script, velocityContext, output);
178 }
179 catch (VelocityException ve) {
180 velocityContext.put("exception", ve.getMessage());
181 velocityContext.put("script", script);
182
183 if (ve instanceof ParseErrorException) {
184 ParseErrorException pe = (ParseErrorException)ve;
185
186 velocityContext.put(
187 "column", new Integer(pe.getColumnNumber()));
188 velocityContext.put(
189 "line", new Integer(pe.getLineNumber()));
190 }
191
192 String velocityTemplateId =
193 PropsValues.JOURNAL_ERROR_TEMPLATE_VELOCITY;
194 String velocityTemplateContent = ContentUtil.get(
195 PropsValues.JOURNAL_ERROR_TEMPLATE_VELOCITY);
196
197 load = VelocityEngineUtil.mergeTemplate(
198 velocityTemplateId, velocityTemplateContent,
199 velocityContext, output);
200 }
201 }
202 catch (Exception e) {
203 if (e instanceof DocumentException) {
204 throw new TransformException("Unable to read XML document", e);
205 }
206 else if (e instanceof VelocityException) {
207 VelocityException pex = (VelocityException)e;
208
209 throw new TransformException(
210 "Unable to parse velocity template: " +
211 HtmlUtil.escape(pex.getMessage()),
212 e);
213 }
214 else if (e instanceof IOException) {
215 throw new TransformException(
216 "Error reading velocity template", e);
217 }
218 else if (e instanceof TransformException) {
219 throw (TransformException)e;
220 }
221 else {
222 throw new TransformException("Unhandled exception", e);
223 }
224 }
225
226 if (!load) {
227 throw new TransformException(
228 "Unable to dynamically load velocity transform script");
229 }
230
231 return output.toString();
232 }
233
234 protected static String injectEditInPlace(String xml, String script)
235 throws DocumentException {
236
237 Document doc = SAXReaderUtil.read(xml);
238
239 List<Node> nodes = doc.selectNodes("//dynamic-element");
240
241 for (Node node : nodes) {
242 Element el = (Element)node;
243
244 String name = GetterUtil.getString(el.attributeValue("name"));
245 String type = GetterUtil.getString(el.attributeValue("type"));
246
247 if ((!name.startsWith("reserved-")) &&
248 (type.equals("text") || type.equals("text_box") ||
249 type.equals("text_area"))) {
250
251 script = wrapField(script, name, type, "data");
252 script = wrapField(script, name, type, "getData()");
253 }
254 }
255
256 return script;
257 }
258
259 protected static Map<String, Object> insertRequestVariables(
260 Element parent) {
261
262 Map<String, Object> map = new HashMap<String, Object>();
263
264 if (parent == null) {
265 return map;
266 }
267
268 for (Element el : parent.elements()) {
269 String name = el.getName();
270
271 if (name.equals("attribute")) {
272 map.put(el.elementText("name"), el.elementText("value"));
273 }
274 else if (name.equals("parameter")) {
275 name = el.element("name").getText();
276
277 List<Element> valueEls = el.elements("value");
278
279 if (valueEls.size() == 1) {
280 map.put(name, (valueEls.get(0)).getText());
281 }
282 else {
283 List<String> values = new ArrayList<String>();
284
285 for (Element valueEl : valueEls) {
286 values.add(valueEl.getText());
287 }
288
289 map.put(name, values);
290 }
291 }
292 else if (el.elements().size() > 0) {
293 map.put(name, insertRequestVariables(el));
294 }
295 else {
296 map.put(name, el.getText());
297 }
298 }
299
300 return map;
301 }
302
303 protected static String wrapField(
304 String script, String name, String type, String call) {
305
306 String field = "$" + name + "." + call;
307 String wrappedField =
308 "<span class=\"journal-content-eip-" + type + "\" " +
309 "id=\"journal-content-field-name-" + name + "\">" + field +
310 "</span>";
311
312 return StringUtil.replace(
313 script, "$editInPlace(" + field + ")", wrappedField);
314 }
315
316 }