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