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.StringPool;
27 import com.liferay.portal.kernel.util.StringUtil;
28 import com.liferay.portal.util.PropsUtil;
29 import com.liferay.portal.velocity.VelocityResourceListener;
30 import com.liferay.portal.velocity.VelocityVariables;
31 import com.liferay.portlet.journal.TransformException;
32 import com.liferay.util.Html;
33 import com.liferay.util.PwdGenerator;
34 import com.liferay.util.xml.CDATAUtil;
35
36 import java.io.IOException;
37 import java.io.StringReader;
38 import java.io.StringWriter;
39
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Map;
45
46 import org.apache.velocity.VelocityContext;
47 import org.apache.velocity.app.Velocity;
48 import org.apache.velocity.exception.VelocityException;
49
50 import org.dom4j.Document;
51 import org.dom4j.DocumentException;
52 import org.dom4j.Element;
53 import org.dom4j.io.SAXReader;
54
55
63 public class JournalVmUtil {
64
65 public static final String[] _TEMPLATE_VELOCITY_RESTRICTED_VARIABLES =
66 PropsUtil.getArray(
67 PropsUtil.JOURNAL_TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
68
69 public static String transform(
70 Map tokens, String languageId, String xml, String script)
71 throws TransformException {
72
73 StringWriter output = new StringWriter();
74
75 boolean load = false;
76
77 try {
78 VelocityContext context = new VelocityContext();
79
80 SAXReader reader = new SAXReader();
81
82 Document doc = reader.read(new StringReader(xml));
83
84 Element root = doc.getRootElement();
85
86 List nodes = _extractDynamicContents(root);
87
88 Iterator itr = nodes.iterator();
89
90 while (itr.hasNext()) {
91 TemplateNode node = (TemplateNode)itr.next();
92
93 context.put(node.getName(), node);
94 }
95
96 context.put(
97 "request", _insertRequestVariables(root.element("request")));
98
99 long companyId = GetterUtil.getLong(
100 (String)tokens.get("company_id"));
101 long groupId = GetterUtil.getLong((String)tokens.get("group_id"));
102 String journalTemplatesPath =
103 VelocityResourceListener.JOURNAL_SEPARATOR + StringPool.SLASH +
104 companyId + StringPool.SLASH + groupId;
105 String randomNamespace =
106 PwdGenerator.getPassword(PwdGenerator.KEY3, 4) +
107 StringPool.UNDERLINE;
108
109 context.put("companyId", String.valueOf(companyId));
110 context.put("groupId", String.valueOf(groupId));
111 context.put("journalTemplatesPath", journalTemplatesPath);
112 context.put("randomNamespace", randomNamespace);
113
114 VelocityVariables.insertHelperUtilities(
115 context, _TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
116
117 script = _injectEditInPlace(xml, script);
118
119 load = Velocity.evaluate(
120 context, output, JournalVmUtil.class.getName(), script);
121 }
122 catch (Exception e) {
123 if (e instanceof DocumentException) {
124 throw new TransformException("Unable to read XML document", e);
125 }
126 else if (e instanceof VelocityException) {
127 VelocityException pex = (VelocityException)e;
128
129 throw new TransformException(
130 "Unable to parse velocity template: " +
131 Html.escape(pex.getMessage()),
132 e);
133 }
134 else if (e instanceof IOException) {
135 throw new TransformException(
136 "Error reading velocity template", e);
137 }
138 else if (e instanceof TransformException) {
139 throw (TransformException)e;
140 }
141 else {
142 throw new TransformException("Unhandled exception", e);
143 }
144 }
145
146 if (!load) {
147 throw new TransformException(
148 "Unable to dynamically load velocity transform script");
149 }
150
151 return output.toString();
152 }
153
154 private static List _extractDynamicContents(Element parent)
155 throws TransformException {
156
157 List nodes = new ArrayList();
158
159 Iterator itr1 = parent.elementIterator("dynamic-element");
160
161 while (itr1.hasNext()) {
162 Element element = (Element)itr1.next();
163
164 Element content = element.element("dynamic-content");
165
166 if (content == null) {
167 throw new TransformException(
168 "Element missing \"dynamic-content\"");
169 }
170
171 String name = element.attributeValue("name", "");
172
173 if (name.length() == 0) {
174 throw new TransformException(
175 "Element missing \"name\" attribute");
176 }
177
178 String type = element.attributeValue("type", "");
179
180 TemplateNode node = new TemplateNode(
181 name, CDATAUtil.strip(content.getText()), type);
182
183 if (element.element("dynamic-element") != null) {
184 node.appendChildren(_extractDynamicContents(element));
185 }
186 else if (content.element("option") != null) {
187 Iterator itr2 = content.elementIterator("option");
188
189 while (itr2.hasNext()) {
190 Element option = (Element)itr2.next();
191
192 node.appendOption(CDATAUtil.strip(option.getText()));
193 }
194 }
195
196 nodes.add(node);
197 }
198
199 return nodes;
200 }
201
202 private static String _injectEditInPlace(String xml, String script)
203 throws DocumentException {
204
205 SAXReader reader = new SAXReader();
206
207 Document doc = reader.read(new StringReader(xml));
208
209 Iterator itr = doc.selectNodes("//dynamic-element").iterator();
210
211 while (itr.hasNext()) {
212 Element el = (Element)itr.next();
213
214 String name = GetterUtil.getString(el.attributeValue("name"));
215 String type = GetterUtil.getString(el.attributeValue("type"));
216
217 if ((!name.startsWith("reserved-")) &&
218 (type.equals("text") || type.equals("text_box") ||
219 type.equals("text_area"))) {
220
221 script = _wrapField(script, name, type, "data");
222 script = _wrapField(script, name, type, "getData()");
223 }
224 }
225
226 return script;
227 }
228
229 private static Map _insertRequestVariables(Element parent) {
230 Map map = new HashMap();
231
232 if (parent == null) {
233 return map;
234 }
235
236 Iterator itr1 = parent.elements().iterator();
237
238 while (itr1.hasNext()) {
239 Element el = (Element)itr1.next();
240
241 String name = el.getName();
242
243 if (name.equals("attribute")) {
244 map.put(el.elementText("name"), el.elementText("value"));
245 }
246 else if (name.equals("parameter")) {
247 name = el.element("name").getText();
248
249 List valueEls = el.elements("value");
250
251 if (valueEls.size() == 1) {
252 map.put(name, ((Element)valueEls.get(0)).getText());
253 }
254 else {
255 List values = new ArrayList();
256
257 Iterator itr2 = valueEls.iterator();
258
259 while (itr2.hasNext()) {
260 Element valueEl = (Element)itr2.next();
261
262 values.add(valueEl.getText());
263 }
264
265 map.put(name, values);
266 }
267 }
268 else if (el.elements().size() > 0) {
269 map.put(name, _insertRequestVariables(el));
270 }
271 else {
272 map.put(name, el.getText());
273 }
274 }
275
276 return map;
277 }
278
279 private static String _wrapField(
280 String script, String name, String type, String call) {
281
282 String field = "$" + name + "." + call;
283 String wrappedField =
284 "<span class=\"journal-content-eip-" + type + "\" " +
285 "id=\"journal-content-field-name-" + name + "\">" + field +
286 "</span>";
287
288 return StringUtil.replace(
289 script, "$editInPlace(" + field + ")", wrappedField);
290 }
291
292 }