001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.dynamicdatamapping.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
020    import com.liferay.portal.kernel.json.JSONArray;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.template.Template;
024    import com.liferay.portal.kernel.template.TemplateConstants;
025    import com.liferay.portal.kernel.template.TemplateContextType;
026    import com.liferay.portal.kernel.template.TemplateManagerUtil;
027    import com.liferay.portal.kernel.template.TemplateResource;
028    import com.liferay.portal.kernel.template.URLTemplateResource;
029    import com.liferay.portal.kernel.util.ArrayUtil;
030    import com.liferay.portal.kernel.util.CharPool;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.HtmlUtil;
033    import com.liferay.portal.kernel.util.LocaleUtil;
034    import com.liferay.portal.kernel.util.LocalizationUtil;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.kernel.xml.Attribute;
040    import com.liferay.portal.kernel.xml.Document;
041    import com.liferay.portal.kernel.xml.DocumentException;
042    import com.liferay.portal.kernel.xml.Element;
043    import com.liferay.portal.kernel.xml.Node;
044    import com.liferay.portal.kernel.xml.SAXReaderUtil;
045    import com.liferay.portal.kernel.xml.XPath;
046    import com.liferay.portal.util.PortalUtil;
047    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
048    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
050    import com.liferay.portlet.dynamicdatamapping.service.DDMStorageLinkLocalServiceUtil;
051    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureServiceUtil;
052    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateServiceUtil;
053    import com.liferay.portlet.dynamicdatamapping.storage.Field;
054    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
055    import com.liferay.util.PwdGenerator;
056    import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
057    
058    import freemarker.ext.servlet.HttpRequestHashModel;
059    import freemarker.ext.servlet.ServletContextHashModel;
060    
061    import freemarker.template.ObjectWrapper;
062    import freemarker.template.TemplateHashModel;
063    
064    import java.io.IOException;
065    import java.io.Writer;
066    
067    import java.net.URL;
068    
069    import java.util.HashMap;
070    import java.util.List;
071    import java.util.Locale;
072    import java.util.Map;
073    
074    import javax.servlet.GenericServlet;
075    import javax.servlet.Servlet;
076    import javax.servlet.ServletException;
077    import javax.servlet.ServletRequest;
078    import javax.servlet.ServletResponse;
079    import javax.servlet.http.HttpServletRequest;
080    import javax.servlet.http.HttpServletResponse;
081    import javax.servlet.jsp.PageContext;
082    
083    /**
084     * @author Bruno Basto
085     * @author Eduardo Lundgren
086     * @author Brian Wing Shun Chan
087     * @author Marcellus Tavares
088     */
089    public class DDMXSDImpl implements DDMXSD {
090    
091            public DDMXSDImpl() {
092                    String defaultTemplateId = _TPL_PATH + "alloy/text.ftl";
093    
094                    URL defaultTemplateURL = getResource(defaultTemplateId);
095    
096                    _defaultTemplateResource = new URLTemplateResource(
097                            defaultTemplateId, defaultTemplateURL);
098    
099                    String defaultReadOnlyTemplateId = _TPL_PATH + "readonly/default.ftl";
100    
101                    URL defaultReadOnlyTemplateURL = getResource(defaultReadOnlyTemplateId);
102    
103                    _defaultReadOnlyTemplateResource = new URLTemplateResource(
104                            defaultReadOnlyTemplateId, defaultReadOnlyTemplateURL);
105            }
106    
107            public String getFieldHTML(
108                            PageContext pageContext, Element element, Fields fields,
109                            String namespace, String mode, boolean readOnly, Locale locale)
110                    throws Exception {
111    
112                    HttpServletRequest request =
113                            (HttpServletRequest)pageContext.getRequest();
114    
115                    String portletId = PortalUtil.getPortletId(request);
116    
117                    String portletNamespace = PortalUtil.getPortletNamespace(portletId);
118    
119                    Map<String, Object> freeMarkerContext = getFreeMarkerContext(
120                            pageContext, portletNamespace, namespace, element, locale);
121    
122                    Map<String, Object> fieldStructure =
123                            (Map<String, Object>)freeMarkerContext.get("fieldStructure");
124    
125                    int fieldRepetition = 1;
126    
127                    DDMFieldsCounter ddmFieldsCounter = getFieldsCounter(
128                            pageContext, fields, portletNamespace, namespace);
129    
130                    String name = element.attributeValue("name");
131    
132                    if (fields != null) {
133                            freeMarkerContext.put("fields", fields);
134    
135                            Field fieldsDisplayField = fields.get(DDMImpl.FIELDS_DISPLAY_NAME);
136    
137                            if ((fieldsDisplayField != null) && fields.contains(name)) {
138                                    String[] fieldsDisplayValues = DDMUtil.getFieldsDisplayValues(
139                                            fieldsDisplayField);
140    
141                                    Map<String, Object> parentFieldStructure =
142                                            (Map<String, Object>)freeMarkerContext.get(
143                                                    "parentFieldStructure");
144    
145                                    String parentFieldName = (String)parentFieldStructure.get(
146                                            "name");
147    
148                                    int offset = ddmFieldsCounter.get(DDMImpl.FIELDS_DISPLAY_NAME);
149    
150                                    fieldRepetition = countFieldRepetition(
151                                            fieldsDisplayValues, parentFieldName, offset);
152                            }
153                    }
154    
155                    StringBundler sb = new StringBundler(fieldRepetition);
156    
157                    while (fieldRepetition > 0) {
158                            fieldStructure.put("fieldNamespace", PwdGenerator.getPassword(4));
159                            fieldStructure.put("valueIndex", ddmFieldsCounter.get(name));
160    
161                            if ((fields != null) && fields.contains(name)) {
162                                    ddmFieldsCounter.incrementKey(name);
163                                    ddmFieldsCounter.incrementKey(DDMImpl.FIELDS_DISPLAY_NAME);
164                            }
165    
166                            String childrenHTML = getHTML(
167                                    pageContext, element, fields, namespace, mode, readOnly,
168                                    locale);
169    
170                            fieldStructure.put("children", childrenHTML);
171    
172                            sb.append(
173                                    processFTL(
174                                            pageContext, element, mode, readOnly, freeMarkerContext));
175    
176                            fieldRepetition--;
177                    }
178    
179                    return sb.toString();
180            }
181    
182            public String getFieldHTMLByName(
183                            PageContext pageContext, long classNameId, long classPK,
184                            String fieldName, Fields fields, String namespace, String mode,
185                            boolean readOnly, Locale locale)
186                    throws Exception {
187    
188                    String xsd = getXSD(classNameId, classPK);
189    
190                    Document document = SAXReaderUtil.read(xsd);
191    
192                    String xPathExpression =
193                            "//dynamic-element[@name=".concat(
194                                    HtmlUtil.escapeXPathAttribute(fieldName)).concat("]");
195    
196                    XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
197    
198                    Node node = xPathSelector.selectSingleNode(document.getRootElement());
199    
200                    Element element = (Element)node.asXPathResult(node.getParent());
201    
202                    return getFieldHTML(
203                            pageContext, element, fields, namespace, mode, readOnly, locale);
204            }
205    
206            public String getHTML(
207                            PageContext pageContext, DDMStructure ddmStructure, Fields fields,
208                            String namespace, boolean readOnly, Locale locale)
209                    throws Exception {
210    
211                    return getHTML(
212                            pageContext, ddmStructure.getXsd(), fields, namespace, readOnly,
213                            locale);
214            }
215    
216            public String getHTML(
217                            PageContext pageContext, DDMTemplate ddmTemplate, Fields fields,
218                            String namespace, boolean readOnly, Locale locale)
219                    throws Exception {
220    
221                    return getHTML(
222                            pageContext, ddmTemplate.getScript(), fields, namespace,
223                            ddmTemplate.getMode(), readOnly, locale);
224            }
225    
226            public String getHTML(
227                            PageContext pageContext, Element element, Fields fields,
228                            Locale locale)
229                    throws Exception {
230    
231                    return getHTML(
232                            pageContext, element, fields, StringPool.BLANK, null, false,
233                            locale);
234            }
235    
236            public String getHTML(
237                            PageContext pageContext, Element element, Fields fields,
238                            String namespace, String mode, boolean readOnly, Locale locale)
239                    throws Exception {
240    
241                    List<Element> dynamicElementElements = element.elements(
242                            "dynamic-element");
243    
244                    StringBundler sb = new StringBundler(dynamicElementElements.size());
245    
246                    for (Element dynamicElementElement : dynamicElementElements) {
247                            sb.append(
248                                    getFieldHTML(
249                                            pageContext, dynamicElementElement, fields, namespace, mode,
250                                            readOnly, locale));
251                    }
252    
253                    return sb.toString();
254            }
255    
256            public String getHTML(
257                            PageContext pageContext, Element element, Locale locale)
258                    throws Exception {
259    
260                    return getHTML(pageContext, element, null, locale);
261            }
262    
263            public String getHTML(
264                            PageContext pageContext, String xml, Fields fields, Locale locale)
265                    throws Exception {
266    
267                    return getHTML(pageContext, xml, fields, StringPool.BLANK, locale);
268            }
269    
270            public String getHTML(
271                            PageContext pageContext, String xml, Fields fields,
272                            String namespace, boolean readOnly, Locale locale)
273                    throws Exception {
274    
275                    return getHTML(
276                            pageContext, xml, fields, namespace, null, readOnly, locale);
277            }
278    
279            public String getHTML(
280                            PageContext pageContext, String xml, Fields fields,
281                            String namespace, Locale locale)
282                    throws Exception {
283    
284                    return getHTML(pageContext, xml, fields, namespace, false, locale);
285            }
286    
287            public String getHTML(
288                            PageContext pageContext, String xml, Fields fields,
289                            String namespace, String mode, boolean readOnly, Locale locale)
290                    throws Exception {
291    
292                    Document document = SAXReaderUtil.read(xml);
293    
294                    return getHTML(
295                            pageContext, document.getRootElement(), fields, namespace, mode,
296                            readOnly, locale);
297            }
298    
299            public String getHTML(PageContext pageContext, String xml, Locale locale)
300                    throws Exception {
301    
302                    return getHTML(pageContext, xml, null, locale);
303            }
304    
305            public JSONArray getJSONArray(DDMStructure structure, String xsd)
306                    throws PortalException, SystemException {
307    
308                    JSONArray jsonArray = null;
309    
310                    if (Validator.isNull(xsd)) {
311                            jsonArray = getJSONArray(structure.getDocument());
312                    }
313                    else {
314                            jsonArray = getJSONArray(xsd);
315                    }
316    
317                    addStructureFieldAttributes(structure, jsonArray);
318    
319                    return jsonArray;
320            }
321    
322            public JSONArray getJSONArray(Document document) throws PortalException {
323                    return getJSONArray(document.getRootElement());
324            }
325    
326            public JSONArray getJSONArray(Element element) throws PortalException {
327                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
328    
329                    Document document = element.getDocument();
330    
331                    String defaultLocale = LocalizationUtil.getDefaultLocale(
332                            document.asXML());
333    
334                    List<Element> dynamicElementElements = element.elements(
335                            "dynamic-element");
336    
337                    for (Element dynamicElementElement : dynamicElementElements) {
338                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
339                            JSONObject localizationMapJSONObject =
340                                    JSONFactoryUtil.createJSONObject();
341    
342                            for (Attribute attribute : dynamicElementElement.attributes()) {
343                                    jsonObject.put(attribute.getName(), attribute.getValue());
344                            }
345    
346                            jsonObject.put("autoGeneratedName", false);
347                            jsonObject.put("id", dynamicElementElement.attributeValue("name"));
348    
349                            String type = jsonObject.getString("type");
350    
351                            List<Element> metadataElements = dynamicElementElement.elements(
352                                    "meta-data");
353    
354                            for (Element metadataElement : metadataElements) {
355                                    if (metadataElement == null) {
356                                            continue;
357                                    }
358    
359                                    String locale = metadataElement.attributeValue("locale");
360    
361                                    JSONObject localeMap = JSONFactoryUtil.createJSONObject();
362    
363                                    for (Element metadataEntryElement :
364                                                    metadataElement.elements()) {
365    
366                                            String attributeName = metadataEntryElement.attributeValue(
367                                                    "name");
368                                            String attributeValue = metadataEntryElement.getTextTrim();
369    
370                                            putMetadataValue(
371                                                    localeMap, attributeName, attributeValue, type);
372    
373                                            if (defaultLocale.equals(locale)) {
374                                                    putMetadataValue(
375                                                            jsonObject, attributeName, attributeValue, type);
376                                            }
377                                    }
378    
379                                    localizationMapJSONObject.put(locale, localeMap);
380                            }
381    
382                            jsonObject.put("localizationMap", localizationMapJSONObject);
383    
384                            JSONArray hiddenAttributesJSONArray =
385                                    JSONFactoryUtil.createJSONArray();
386    
387                            if (type.equals(DDMImpl.TYPE_CHECKBOX)) {
388                                    hiddenAttributesJSONArray.put("required");
389                            }
390    
391                            if (type.equals(DDMImpl.TYPE_DDM_FILEUPLOAD)) {
392                                    hiddenAttributesJSONArray.put("predefinedValue");
393                            }
394    
395                            hiddenAttributesJSONArray.put("readOnly");
396    
397                            jsonObject.put("hiddenAttributes", hiddenAttributesJSONArray);
398    
399                            String key = "fields";
400    
401                            if (type.equals(DDMImpl.TYPE_RADIO) ||
402                                    type.equals(DDMImpl.TYPE_SELECT)) {
403    
404                                    key = "options";
405                            }
406    
407                            jsonObject.put(key, getJSONArray(dynamicElementElement));
408    
409                            jsonArray.put(jsonObject);
410                    }
411    
412                    return jsonArray;
413            }
414    
415            public JSONArray getJSONArray(String xml)
416                    throws PortalException, SystemException {
417    
418                    try {
419                            return getJSONArray(SAXReaderUtil.read(xml));
420                    }
421                    catch (DocumentException de) {
422                            throw new SystemException();
423                    }
424            }
425    
426            public String getXSD(long classNameId, long classPK)
427                    throws PortalException, SystemException {
428    
429                    if ((classNameId <= 0) || (classPK <= 0)) {
430                            return null;
431                    }
432    
433                    long ddmStructureClassNameId = PortalUtil.getClassNameId(
434                            DDMStructure.class);
435    
436                    long ddmTemplateClassNameId = PortalUtil.getClassNameId(
437                            DDMTemplate.class);
438    
439                    if (classNameId == ddmStructureClassNameId) {
440                            DDMStructure structure = DDMStructureServiceUtil.getStructure(
441                                    classPK);
442    
443                            return structure.getCompleteXsd();
444                    }
445                    else if (classNameId == ddmTemplateClassNameId) {
446                            DDMTemplate template = DDMTemplateServiceUtil.getTemplate(classPK);
447    
448                            return template.getScript();
449                    }
450    
451                    return null;
452            }
453    
454            protected JSONArray addStructureFieldAttributes(
455                    DDMStructure structure, JSONArray jsonArray) {
456    
457                    for (int i = 0; i < jsonArray.length(); i++) {
458                            JSONObject jsonObject = jsonArray.getJSONObject(i);
459    
460                            String fieldName = jsonObject.getString("name");
461    
462                            jsonObject.put(
463                                    "readOnlyAttributes",
464                                    getStructureFieldReadOnlyAttributes(structure, fieldName));
465                    }
466    
467                    return jsonArray;
468            }
469    
470            protected int countFieldRepetition(
471                    String[] fieldsDisplayValues, String parentFieldName, int offset) {
472    
473                    int total = 0;
474    
475                    String fieldName = fieldsDisplayValues[offset];
476    
477                    for (; offset < fieldsDisplayValues.length; offset++) {
478                            String fieldNameValue = fieldsDisplayValues[offset];
479    
480                            if (fieldNameValue.equals(fieldName)) {
481                                    total++;
482                            }
483    
484                            if (fieldNameValue.equals(parentFieldName)) {
485                                    break;
486                            }
487                    }
488    
489                    return total;
490            }
491    
492            protected Map<String, Object> getFieldContext(
493                    PageContext pageContext, String portletNamespace, String namespace,
494                    Element dynamicElementElement, Locale locale) {
495    
496                    Map<String, Map<String, Object>> fieldsContext = getFieldsContext(
497                            pageContext, portletNamespace, namespace);
498    
499                    String name = dynamicElementElement.attributeValue("name");
500    
501                    Map<String, Object> fieldContext = fieldsContext.get(name);
502    
503                    if (fieldContext != null) {
504                            return fieldContext;
505                    }
506    
507                    Document document = dynamicElementElement.getDocument();
508    
509                    String xml = document.asXML();
510    
511                    String[] availableLocales = LocalizationUtil.getAvailableLocales(xml);
512    
513                    String defaultLanguageId = LocalizationUtil.getDefaultLocale(xml);
514    
515                    String languageId = LocaleUtil.toLanguageId(locale);
516    
517                    if (!ArrayUtil.contains(availableLocales, languageId)) {
518                            languageId = defaultLanguageId;
519                    }
520    
521                    Element metadataElement =
522                            (Element)dynamicElementElement.selectSingleNode(
523                                    "meta-data[@locale='" + languageId + "']");
524    
525                    fieldContext = new HashMap<String, Object>();
526    
527                    if (metadataElement != null) {
528                            for (Element metadataEntry : metadataElement.elements()) {
529                                    fieldContext.put(
530                                            metadataEntry.attributeValue("name"),
531                                            metadataEntry.getText());
532                            }
533                    }
534    
535                    for (Attribute attribute : dynamicElementElement.attributes()) {
536                            fieldContext.put(attribute.getName(), attribute.getValue());
537                    }
538    
539                    fieldContext.put("fieldNamespace", PwdGenerator.getPassword(4));
540    
541                    fieldsContext.put(name, fieldContext);
542    
543                    return fieldContext;
544            }
545    
546            protected Map<String, Map<String, Object>> getFieldsContext(
547                    PageContext pageContext, String portletNamespace, String namespace) {
548    
549                    String fieldsContextKey =
550                            portletNamespace + namespace + "fieldsContext";
551    
552                    Map<String, Map<String, Object>> fieldsContext =
553                            (Map<String, Map<String, Object>>)pageContext.getAttribute(
554                                    fieldsContextKey);
555    
556                    if (fieldsContext == null) {
557                            fieldsContext = new HashMap<String, Map<String, Object>>();
558    
559                            pageContext.setAttribute(fieldsContextKey, fieldsContext);
560                    }
561    
562                    return fieldsContext;
563            }
564    
565            protected DDMFieldsCounter getFieldsCounter(
566                    PageContext pageContext, Fields fields, String portletNamespace,
567                    String namespace) {
568    
569                    String fieldsCounterKey = portletNamespace + namespace + "fieldsCount";
570    
571                    DDMFieldsCounter ddmFieldsCounter =
572                            (DDMFieldsCounter)pageContext.getAttribute(fieldsCounterKey);
573    
574                    if (ddmFieldsCounter == null) {
575                            ddmFieldsCounter = new DDMFieldsCounter();
576    
577                            pageContext.setAttribute(fieldsCounterKey, ddmFieldsCounter);
578                    }
579    
580                    return ddmFieldsCounter;
581            }
582    
583            protected Map<String, Object> getFreeMarkerContext(
584                    PageContext pageContext, String portletNamespace, String namespace,
585                    Element dynamicElementElement, Locale locale) {
586    
587                    Map<String, Object> freeMarkerContext = new HashMap<String, Object>();
588    
589                    Map<String, Object> fieldContext = getFieldContext(
590                            pageContext, portletNamespace, namespace, dynamicElementElement,
591                            locale);
592    
593                    Map<String, Object> parentFieldContext = new HashMap<String, Object>();
594    
595                    Element parentElement = dynamicElementElement.getParent();
596    
597                    if (parentElement != null) {
598                            parentFieldContext = getFieldContext(
599                                    pageContext, portletNamespace, namespace, parentElement,
600                                    locale);
601                    }
602    
603                    freeMarkerContext.put("fieldStructure", fieldContext);
604                    freeMarkerContext.put("namespace", namespace);
605                    freeMarkerContext.put("parentFieldStructure", parentFieldContext);
606                    freeMarkerContext.put("portletNamespace", portletNamespace);
607                    freeMarkerContext.put("requestedLocale", locale);
608    
609                    return freeMarkerContext;
610            }
611    
612            protected URL getResource(String name) {
613                    Class<?> clazz = getClass();
614    
615                    ClassLoader classLoader = clazz.getClassLoader();
616    
617                    return classLoader.getResource(name);
618            }
619    
620            protected JSONArray getStructureFieldReadOnlyAttributes(
621                    DDMStructure structure, String fieldName) {
622    
623                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
624    
625                    try {
626                            if (DDMStorageLinkLocalServiceUtil.getStructureStorageLinksCount(
627                                            structure.getStructureId()) > 0) {
628    
629                                    jsonArray.put("name");
630                            }
631                    }
632                    catch (Exception e) {
633                    }
634    
635                    return jsonArray;
636            }
637    
638            protected String processFTL(
639                            PageContext pageContext, Element element, String mode,
640                            boolean readOnly, Map<String, Object> freeMarkerContext)
641                    throws Exception {
642    
643                    String fieldNamespace = element.attributeValue(
644                            "fieldNamespace", _DEFAULT_NAMESPACE);
645    
646                    TemplateResource templateResource = _defaultTemplateResource;
647    
648                    Map<String, Object> fieldStructure =
649                            (Map<String, Object>)freeMarkerContext.get("fieldStructure");
650    
651                    boolean fieldReadOnly = GetterUtil.getBoolean(
652                            fieldStructure.get("readOnly"));
653    
654                    if ((fieldReadOnly && Validator.isNotNull(mode) &&
655                             mode.equalsIgnoreCase(
656                                    DDMTemplateConstants.TEMPLATE_MODE_EDIT)) || readOnly) {
657    
658                            fieldNamespace = _DEFAULT_READ_ONLY_NAMESPACE;
659    
660                            templateResource = _defaultReadOnlyTemplateResource;
661                    }
662    
663                    String type = element.attributeValue("type");
664    
665                    String templateName = StringUtil.replaceFirst(
666                            type, fieldNamespace.concat(StringPool.DASH), StringPool.BLANK);
667    
668                    StringBundler resourcePath = new StringBundler(5);
669    
670                    resourcePath.append(_TPL_PATH);
671                    resourcePath.append(fieldNamespace.toLowerCase());
672                    resourcePath.append(CharPool.SLASH);
673                    resourcePath.append(templateName);
674                    resourcePath.append(_TPL_EXT);
675    
676                    String resource = resourcePath.toString();
677    
678                    URL url = getResource(resource);
679    
680                    if (url != null) {
681                            templateResource = new URLTemplateResource(resource, url);
682                    }
683    
684                    if (templateResource == null) {
685                            throw new Exception("Unable to load template resource " + resource);
686                    }
687    
688                    Template template = TemplateManagerUtil.getTemplate(
689                            TemplateConstants.LANG_TYPE_FTL, templateResource,
690                            TemplateContextType.STANDARD);
691    
692                    for (Map.Entry<String, Object> entry : freeMarkerContext.entrySet()) {
693                            template.put(entry.getKey(), entry.getValue());
694                    }
695    
696                    return processFTL(pageContext, template);
697            }
698    
699            /**
700             * @see com.liferay.taglib.util.ThemeUtil#includeFTL
701             */
702            protected String processFTL(PageContext pageContext, Template template)
703                    throws Exception {
704    
705                    HttpServletRequest request =
706                            (HttpServletRequest)pageContext.getRequest();
707    
708                    // FreeMarker variables
709    
710                    template.prepare(request);
711    
712                    // Tag libraries
713    
714                    HttpServletResponse response =
715                            (HttpServletResponse)pageContext.getResponse();
716    
717                    Writer writer = new UnsyncStringWriter();
718    
719                    // Portal JSP tag library factory
720    
721                    TemplateHashModel portalTaglib =
722                            FreeMarkerTaglibFactoryUtil.createTaglibFactory(
723                                    pageContext.getServletContext());
724    
725                    template.put("PortalJspTagLibs", portalTaglib);
726    
727                    // FreeMarker JSP tag library support
728    
729                    final Servlet servlet = (Servlet)pageContext.getPage();
730    
731                    GenericServlet genericServlet = null;
732    
733                    if (servlet instanceof GenericServlet) {
734                            genericServlet = (GenericServlet)servlet;
735                    }
736                    else {
737                            genericServlet = new GenericServlet() {
738    
739                                    @Override
740                                    public void service(
741                                                    ServletRequest servletRequest,
742                                                    ServletResponse servletResponse)
743                                            throws IOException, ServletException {
744    
745                                            servlet.service(servletRequest, servletResponse);
746                                    }
747    
748                            };
749    
750                            genericServlet.init(pageContext.getServletConfig());
751                    }
752    
753                    ServletContextHashModel servletContextHashModel =
754                            new ServletContextHashModel(
755                                    genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
756    
757                    template.put("Application", servletContextHashModel);
758    
759                    HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
760                            request, response, ObjectWrapper.DEFAULT_WRAPPER);
761    
762                    template.put("Request", httpRequestHashModel);
763    
764                    // Merge templates
765    
766                    template.processTemplate(writer);
767    
768                    return writer.toString();
769            }
770    
771            protected void putMetadataValue(
772                    JSONObject jsonObject, String attributeName, String attributeValue,
773                    String type) {
774    
775                    if (type.equals(DDMImpl.TYPE_RADIO) ||
776                            type.equals(DDMImpl.TYPE_SELECT)) {
777    
778                            if (attributeName.equals("predefinedValue")) {
779                                    try {
780                                            jsonObject.put(
781                                                    attributeName,
782                                                    JSONFactoryUtil.createJSONArray(attributeValue));
783                                    }
784                                    catch (Exception e) {
785                                    }
786    
787                                    return;
788                            }
789                    }
790    
791                    jsonObject.put(attributeName, attributeValue);
792            }
793    
794            private static final String _DEFAULT_NAMESPACE = "alloy";
795    
796            private static final String _DEFAULT_READ_ONLY_NAMESPACE = "readonly";
797    
798            private static final String _TPL_EXT = ".ftl";
799    
800            private static final String _TPL_PATH =
801                    "com/liferay/portlet/dynamicdatamapping/dependencies/";
802    
803            private TemplateResource _defaultReadOnlyTemplateResource;
804            private TemplateResource _defaultTemplateResource;
805    
806    }