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