001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portlet.journal.util;
022:
023: import com.liferay.portal.kernel.util.GetterUtil;
024: import com.liferay.portal.kernel.util.StringPool;
025: import com.liferay.portal.kernel.util.StringUtil;
026: import com.liferay.portal.util.PropsUtil;
027: import com.liferay.portal.velocity.VelocityResourceListener;
028: import com.liferay.portal.velocity.VelocityVariables;
029: import com.liferay.portlet.journal.TransformException;
030: import com.liferay.util.Html;
031: import com.liferay.util.PwdGenerator;
032: import com.liferay.util.xml.CDATAUtil;
033:
034: import java.io.IOException;
035: import java.io.StringReader;
036: import java.io.StringWriter;
037:
038: import java.util.ArrayList;
039: import java.util.HashMap;
040: import java.util.Iterator;
041: import java.util.List;
042: import java.util.Map;
043:
044: import org.apache.velocity.VelocityContext;
045: import org.apache.velocity.app.Velocity;
046: import org.apache.velocity.exception.VelocityException;
047:
048: import org.dom4j.Document;
049: import org.dom4j.DocumentException;
050: import org.dom4j.Element;
051: import org.dom4j.io.SAXReader;
052:
053: /**
054: * <a href="JournalVmUtil.java.html"><b><i>View Source</i></b></a>
055: *
056: * @author Alexander Chow
057: * @author Brian Wing Shun Chan
058: * @author Raymond Augé
059: *
060: */
061: public class JournalVmUtil {
062:
063: public static final String[] _TEMPLATE_VELOCITY_RESTRICTED_VARIABLES = PropsUtil
064: .getArray(PropsUtil.JOURNAL_TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
065:
066: public static String transform(Map tokens, String languageId,
067: String xml, String script) throws TransformException {
068:
069: StringWriter output = new StringWriter();
070:
071: boolean load = false;
072:
073: try {
074: VelocityContext context = new VelocityContext();
075:
076: SAXReader reader = new SAXReader();
077:
078: Document doc = reader.read(new StringReader(xml));
079:
080: Element root = doc.getRootElement();
081:
082: List nodes = _extractDynamicContents(root);
083:
084: Iterator itr = nodes.iterator();
085:
086: while (itr.hasNext()) {
087: TemplateNode node = (TemplateNode) itr.next();
088:
089: context.put(node.getName(), node);
090: }
091:
092: context.put("request", _insertRequestVariables(root
093: .element("request")));
094:
095: long companyId = GetterUtil.getLong((String) tokens
096: .get("company_id"));
097: long groupId = GetterUtil.getLong((String) tokens
098: .get("group_id"));
099: String journalTemplatesPath = VelocityResourceListener.JOURNAL_SEPARATOR
100: + StringPool.SLASH
101: + companyId
102: + StringPool.SLASH
103: + groupId;
104: String randomNamespace = PwdGenerator.getPassword(
105: PwdGenerator.KEY3, 4)
106: + StringPool.UNDERLINE;
107:
108: context.put("companyId", String.valueOf(companyId));
109: context.put("groupId", String.valueOf(groupId));
110: context.put("journalTemplatesPath", journalTemplatesPath);
111: context.put("randomNamespace", randomNamespace);
112:
113: VelocityVariables.insertHelperUtilities(context,
114: _TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
115:
116: script = _injectEditInPlace(xml, script);
117:
118: load = Velocity.evaluate(context, output,
119: JournalVmUtil.class.getName(), script);
120: } catch (Exception e) {
121: if (e instanceof DocumentException) {
122: throw new TransformException(
123: "Unable to read XML document", e);
124: } else if (e instanceof VelocityException) {
125: VelocityException pex = (VelocityException) e;
126:
127: throw new TransformException(
128: "Unable to parse velocity template: "
129: + Html.escape(pex.getMessage()), e);
130: } else if (e instanceof IOException) {
131: throw new TransformException(
132: "Error reading velocity template", e);
133: } else if (e instanceof TransformException) {
134: throw (TransformException) e;
135: } else {
136: throw new TransformException("Unhandled exception", e);
137: }
138: }
139:
140: if (!load) {
141: throw new TransformException(
142: "Unable to dynamically load velocity transform script");
143: }
144:
145: return output.toString();
146: }
147:
148: private static List _extractDynamicContents(Element parent)
149: throws TransformException {
150:
151: List nodes = new ArrayList();
152:
153: Iterator itr1 = parent.elementIterator("dynamic-element");
154:
155: while (itr1.hasNext()) {
156: Element element = (Element) itr1.next();
157:
158: Element content = element.element("dynamic-content");
159:
160: if (content == null) {
161: throw new TransformException(
162: "Element missing \"dynamic-content\"");
163: }
164:
165: String name = element.attributeValue("name", "");
166:
167: if (name.length() == 0) {
168: throw new TransformException(
169: "Element missing \"name\" attribute");
170: }
171:
172: String type = element.attributeValue("type", "");
173:
174: TemplateNode node = new TemplateNode(name, CDATAUtil
175: .strip(content.getText()), type);
176:
177: if (element.element("dynamic-element") != null) {
178: node.appendChildren(_extractDynamicContents(element));
179: } else if (content.element("option") != null) {
180: Iterator itr2 = content.elementIterator("option");
181:
182: while (itr2.hasNext()) {
183: Element option = (Element) itr2.next();
184:
185: node
186: .appendOption(CDATAUtil.strip(option
187: .getText()));
188: }
189: }
190:
191: nodes.add(node);
192: }
193:
194: return nodes;
195: }
196:
197: private static String _injectEditInPlace(String xml, String script)
198: throws DocumentException {
199:
200: SAXReader reader = new SAXReader();
201:
202: Document doc = reader.read(new StringReader(xml));
203:
204: Iterator itr = doc.selectNodes("//dynamic-element").iterator();
205:
206: while (itr.hasNext()) {
207: Element el = (Element) itr.next();
208:
209: String name = GetterUtil.getString(el
210: .attributeValue("name"));
211: String type = GetterUtil.getString(el
212: .attributeValue("type"));
213:
214: if ((!name.startsWith("reserved-"))
215: && (type.equals("text") || type.equals("text_box") || type
216: .equals("text_area"))) {
217:
218: script = _wrapField(script, name, type, "data");
219: script = _wrapField(script, name, type, "getData()");
220: }
221: }
222:
223: return script;
224: }
225:
226: private static Map _insertRequestVariables(Element parent) {
227: Map map = new HashMap();
228:
229: if (parent == null) {
230: return map;
231: }
232:
233: Iterator itr1 = parent.elements().iterator();
234:
235: while (itr1.hasNext()) {
236: Element el = (Element) itr1.next();
237:
238: String name = el.getName();
239:
240: if (name.equals("attribute")) {
241: map
242: .put(el.elementText("name"), el
243: .elementText("value"));
244: } else if (name.equals("parameter")) {
245: name = el.element("name").getText();
246:
247: List valueEls = el.elements("value");
248:
249: if (valueEls.size() == 1) {
250: map
251: .put(name, ((Element) valueEls.get(0))
252: .getText());
253: } else {
254: List values = new ArrayList();
255:
256: Iterator itr2 = valueEls.iterator();
257:
258: while (itr2.hasNext()) {
259: Element valueEl = (Element) itr2.next();
260:
261: values.add(valueEl.getText());
262: }
263:
264: map.put(name, values);
265: }
266: } else if (el.elements().size() > 0) {
267: map.put(name, _insertRequestVariables(el));
268: } else {
269: map.put(name, el.getText());
270: }
271: }
272:
273: return map;
274: }
275:
276: private static String _wrapField(String script, String name,
277: String type, String call) {
278:
279: String field = "$" + name + "." + call;
280: String wrappedField = "<span class=\"journal-content-eip-"
281: + type + "\" " + "id=\"journal-content-field-name-"
282: + name + "\">" + field + "</span>";
283:
284: return StringUtil.replace(script,
285: "$editInPlace(" + field + ")", wrappedField);
286: }
287:
288: }
|