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.lar;
016    
017    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
021    import com.liferay.portal.kernel.lar.PortletDataContext;
022    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
023    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.repository.model.FileEntry;
027    import com.liferay.portal.kernel.util.ArrayUtil;
028    import com.liferay.portal.kernel.util.CharPool;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.HttpUtil;
031    import com.liferay.portal.kernel.util.MapUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.kernel.xml.Document;
037    import com.liferay.portal.kernel.xml.Element;
038    import com.liferay.portal.kernel.xml.SAXReaderUtil;
039    import com.liferay.portal.model.Group;
040    import com.liferay.portal.model.Layout;
041    import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
042    import com.liferay.portal.service.GroupLocalServiceUtil;
043    import com.liferay.portal.service.LayoutLocalServiceUtil;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PortletKeys;
046    import com.liferay.portal.util.PropsValues;
047    import com.liferay.portlet.documentlibrary.lar.DLPortletDataHandler;
048    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
049    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
050    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
052    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
053    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
054    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
055    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMStructureActionableDynamicQuery;
056    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMTemplateActionableDynamicQuery;
057    
058    import java.util.ArrayList;
059    import java.util.HashMap;
060    import java.util.List;
061    import java.util.Map;
062    import java.util.regex.Matcher;
063    import java.util.regex.Pattern;
064    
065    import javax.portlet.PortletPreferences;
066    
067    /**
068     * @author Marcellus Tavares
069     * @author Juan Fernández
070     */
071    public class DDMPortletDataHandler extends BasePortletDataHandler {
072    
073            public static final String NAMESPACE = "ddm";
074    
075            public static String exportReferencedContent(
076                            PortletDataContext portletDataContext,
077                            Element dlFileEntryTypesElement, Element dlFoldersElement,
078                            Element dlFileEntriesElement, Element dlFileRanksElement,
079                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
080                            Element entityElement, String content)
081                    throws Exception {
082    
083                    content = exportDLFileEntries(
084                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
085                            dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
086                            dlRepositoryEntriesElement, entityElement, content, false);
087                    content = exportLayoutFriendlyURLs(portletDataContext, content);
088                    content = exportLinksToLayout(portletDataContext, content);
089    
090                    String entityElementName = entityElement.getName();
091    
092                    if (!entityElementName.equals("article")) {
093                            content = StringUtil.replace(
094                                    content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
095                    }
096    
097                    return content;
098            }
099    
100            public DDMPortletDataHandler() {
101                    setAlwaysExportable(true);
102                    setDataLocalized(true);
103                    setExportControls(
104                            new PortletDataHandlerBoolean(NAMESPACE, "structures", true, true),
105                            new PortletDataHandlerBoolean(NAMESPACE, "templates"));
106            }
107    
108            protected static String exportDLFileEntries(
109                            PortletDataContext portletDataContext,
110                            Element dlFileEntryTypesElement, Element dlFoldersElement,
111                            Element dlFileEntriesElement, Element dlFileRanksElement,
112                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
113                            Element entityElement, String content, boolean checkDateRange)
114                    throws Exception {
115    
116                    Group group = GroupLocalServiceUtil.getGroup(
117                            portletDataContext.getGroupId());
118    
119                    if (group.isStagingGroup()) {
120                            group = group.getLiveGroup();
121                    }
122    
123                    if (group.isStaged() && !group.isStagedRemotely() &&
124                            !group.isStagedPortlet(PortletKeys.DOCUMENT_LIBRARY)) {
125    
126                            return content;
127                    }
128    
129                    StringBuilder sb = new StringBuilder(content);
130    
131                    int beginPos = content.length();
132                    int currentLocation = -1;
133    
134                    boolean legacyURL = true;
135    
136                    while (true) {
137                            String contextPath = PortalUtil.getPathContext();
138    
139                            currentLocation = content.lastIndexOf(
140                                    contextPath.concat("/c/document_library/get_file?"), beginPos);
141    
142                            if (currentLocation == -1) {
143                                    currentLocation = content.lastIndexOf(
144                                            contextPath.concat("/image/image_gallery?"), beginPos);
145                            }
146    
147                            if (currentLocation == -1) {
148                                    currentLocation = content.lastIndexOf(
149                                            contextPath.concat("/documents/"), beginPos);
150    
151                                    legacyURL = false;
152                            }
153    
154                            if (currentLocation == -1) {
155                                    return sb.toString();
156                            }
157    
158                            beginPos = currentLocation + contextPath.length();
159    
160                            int endPos1 = content.indexOf(CharPool.APOSTROPHE, beginPos);
161                            int endPos2 = content.indexOf(CharPool.CLOSE_BRACKET, beginPos);
162                            int endPos3 = content.indexOf(CharPool.CLOSE_CURLY_BRACE, beginPos);
163                            int endPos4 = content.indexOf(CharPool.CLOSE_PARENTHESIS, beginPos);
164                            int endPos5 = content.indexOf(CharPool.LESS_THAN, beginPos);
165                            int endPos6 = content.indexOf(CharPool.QUESTION, beginPos);
166                            int endPos7 = content.indexOf(CharPool.QUOTE, beginPos);
167                            int endPos8 = content.indexOf(CharPool.SPACE, beginPos);
168    
169                            int endPos = endPos1;
170    
171                            if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
172                                    endPos = endPos2;
173                            }
174    
175                            if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
176                                    endPos = endPos3;
177                            }
178    
179                            if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
180                                    endPos = endPos4;
181                            }
182    
183                            if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
184                                    endPos = endPos5;
185                            }
186    
187                            if ((endPos == -1) ||
188                                    ((endPos6 != -1) && (endPos6 < endPos) && !legacyURL)) {
189    
190                                    endPos = endPos6;
191                            }
192    
193                            if ((endPos == -1) || ((endPos7 != -1) && (endPos7 < endPos))) {
194                                    endPos = endPos7;
195                            }
196    
197                            if ((endPos == -1) || ((endPos8 != -1) && (endPos8 < endPos))) {
198                                    endPos = endPos8;
199                            }
200    
201                            if ((beginPos == -1) || (endPos == -1)) {
202                                    break;
203                            }
204    
205                            try {
206                                    String oldParameters = content.substring(beginPos, endPos);
207    
208                                    while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
209                                            oldParameters = oldParameters.replace(
210                                                    StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
211                                    }
212    
213                                    Map<String, String[]> map = new HashMap<String, String[]>();
214    
215                                    if (oldParameters.startsWith("/documents/")) {
216                                            String[] pathArray = oldParameters.split(StringPool.SLASH);
217    
218                                            map.put("groupId", new String[] {pathArray[2]});
219    
220                                            if (pathArray.length == 4) {
221                                                    map.put("uuid", new String[] {pathArray[3]});
222                                            }
223                                            else if (pathArray.length == 5) {
224                                                    map.put("folderId", new String[] {pathArray[3]});
225    
226                                                    String title = HttpUtil.decodeURL(pathArray[4]);
227    
228                                                    int pos = title.indexOf(StringPool.QUESTION);
229    
230                                                    if (pos != -1) {
231                                                            title = title.substring(0, pos);
232                                                    }
233    
234                                                    map.put("title", new String[] {title});
235                                            }
236                                            else if (pathArray.length > 5) {
237                                                    String uuid = pathArray[5];
238    
239                                                    int pos = uuid.indexOf(StringPool.QUESTION);
240    
241                                                    if (pos != -1) {
242                                                            uuid = uuid.substring(0, pos);
243                                                    }
244    
245                                                    map.put("uuid", new String[] {uuid});
246                                            }
247                                    }
248                                    else {
249                                            oldParameters = oldParameters.substring(
250                                                    oldParameters.indexOf(CharPool.QUESTION) + 1);
251    
252                                            map = HttpUtil.parameterMapFromString(oldParameters);
253                                    }
254    
255                                    FileEntry fileEntry = null;
256    
257                                    String uuid = MapUtil.getString(map, "uuid");
258    
259                                    if (Validator.isNotNull(uuid)) {
260                                            String groupIdString = MapUtil.getString(map, "groupId");
261    
262                                            long groupId = GetterUtil.getLong(groupIdString);
263    
264                                            if (groupIdString.equals("@group_id@")) {
265                                                    groupId = portletDataContext.getScopeGroupId();
266                                            }
267    
268                                            fileEntry =
269                                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
270                                                            uuid, groupId);
271                                    }
272                                    else {
273                                            String folderIdString = MapUtil.getString(map, "folderId");
274    
275                                            if (Validator.isNotNull(folderIdString)) {
276                                                    long folderId = GetterUtil.getLong(folderIdString);
277                                                    String name = MapUtil.getString(map, "name");
278                                                    String title = MapUtil.getString(map, "title");
279    
280                                                    String groupIdString = MapUtil.getString(
281                                                            map, "groupId");
282    
283                                                    long groupId = GetterUtil.getLong(groupIdString);
284    
285                                                    if (groupIdString.equals("@group_id@")) {
286                                                            groupId = portletDataContext.getScopeGroupId();
287                                                    }
288    
289                                                    if (Validator.isNotNull(title)) {
290                                                            fileEntry = DLAppLocalServiceUtil.getFileEntry(
291                                                                    groupId, folderId, title);
292                                                    }
293                                                    else {
294                                                            DLFileEntry dlFileEntry =
295                                                                    DLFileEntryLocalServiceUtil.getFileEntryByName(
296                                                                            groupId, folderId, name);
297    
298                                                            fileEntry = new LiferayFileEntry(dlFileEntry);
299                                                    }
300                                            }
301                                            else if (map.containsKey("image_id") ||
302                                                    map.containsKey("img_id") ||
303                                                    map.containsKey("i_id")) {
304    
305                                                    long imageId = MapUtil.getLong(map, "image_id");
306    
307                                                    if (imageId <= 0) {
308                                                            imageId = MapUtil.getLong(map, "img_id");
309    
310                                                            if (imageId <= 0) {
311                                                                    imageId = MapUtil.getLong(map, "i_id");
312                                                            }
313                                                    }
314    
315                                                    DLFileEntry dlFileEntry =
316                                                            DLFileEntryLocalServiceUtil.
317                                                                    fetchFileEntryByAnyImageId(imageId);
318    
319                                                    if (dlFileEntry != null) {
320                                                            fileEntry = new LiferayFileEntry(dlFileEntry);
321                                                    }
322                                            }
323                                    }
324    
325                                    if (fileEntry == null) {
326                                            beginPos--;
327    
328                                            continue;
329                                    }
330    
331                                    beginPos = currentLocation;
332    
333                                    DLPortletDataHandler.exportFileEntry(
334                                            portletDataContext, dlFileEntryTypesElement,
335                                            dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
336                                            dlRepositoriesElement, dlRepositoryEntriesElement,
337                                            fileEntry, checkDateRange);
338    
339                                    Element dlReferenceElement = entityElement.addElement(
340                                            "dl-reference");
341    
342                                    dlReferenceElement.addAttribute(
343                                            "default-repository",
344                                            String.valueOf(fileEntry.isDefaultRepository()));
345    
346                                    String path = null;
347    
348                                    if (fileEntry.isDefaultRepository()) {
349                                            path = DLPortletDataHandler.getFileEntryPath(
350                                                    portletDataContext, fileEntry);
351    
352                                    }
353                                    else {
354                                            path = DLPortletDataHandler.getRepositoryEntryPath(
355                                                    portletDataContext, fileEntry.getFileEntryId());
356                                    }
357    
358                                    dlReferenceElement.addAttribute("path", path);
359    
360                                    String dlReference = "[$dl-reference=" + path + "$]";
361    
362                                    sb.replace(beginPos, endPos, dlReference);
363                            }
364                            catch (Exception e) {
365                                    if (_log.isDebugEnabled()) {
366                                            _log.debug(e, e);
367                                    }
368                                    else if (_log.isWarnEnabled()) {
369                                            _log.warn(e.getMessage());
370                                    }
371                            }
372    
373                            beginPos--;
374                    }
375    
376                    return sb.toString();
377            }
378    
379            protected static String exportLayoutFriendlyURLs(
380                    PortletDataContext portletDataContext, String content) {
381    
382                    Group group = null;
383    
384                    try {
385                            group = GroupLocalServiceUtil.getGroup(
386                                    portletDataContext.getScopeGroupId());
387                    }
388                    catch (Exception e) {
389                            if (_log.isWarnEnabled()) {
390                                    _log.warn(e);
391                            }
392    
393                            return content;
394                    }
395    
396                    StringBuilder sb = new StringBuilder(content);
397    
398                    String privateGroupServletMapping =
399                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
400                    String privateUserServletMapping =
401                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
402                    String publicServletMapping =
403                            PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
404    
405                    String portalContextPath = PortalUtil.getPathContext();
406    
407                    if (Validator.isNotNull(portalContextPath)) {
408                            privateGroupServletMapping = portalContextPath.concat(
409                                    privateGroupServletMapping);
410                            privateUserServletMapping = portalContextPath.concat(
411                                    privateUserServletMapping);
412                            publicServletMapping = portalContextPath.concat(
413                                    publicServletMapping);
414                    }
415    
416                    String href = "href=";
417    
418                    int beginPos = content.length();
419    
420                    while (true) {
421                            int hrefLength = href.length();
422    
423                            beginPos = content.lastIndexOf(href, beginPos);
424    
425                            if (beginPos == -1) {
426                                    break;
427                            }
428    
429                            char c = content.charAt(beginPos + hrefLength);
430    
431                            if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) {
432                                    hrefLength++;
433                            }
434    
435                            int endPos1 = content.indexOf(
436                                    CharPool.APOSTROPHE, beginPos + hrefLength);
437                            int endPos2 = content.indexOf(
438                                    CharPool.CLOSE_BRACKET, beginPos + hrefLength);
439                            int endPos3 = content.indexOf(
440                                    CharPool.CLOSE_CURLY_BRACE, beginPos + hrefLength);
441                            int endPos4 = content.indexOf(
442                                    CharPool.CLOSE_PARENTHESIS, beginPos + hrefLength);
443                            int endPos5 = content.indexOf(
444                                    CharPool.LESS_THAN, beginPos + hrefLength);
445                            int endPos6 = content.indexOf(
446                                    CharPool.QUESTION, beginPos + hrefLength);
447                            int endPos7 = content.indexOf(
448                                    CharPool.QUOTE, beginPos + hrefLength);
449                            int endPos8 = content.indexOf(
450                                    CharPool.SPACE, beginPos + hrefLength);
451    
452                            int endPos = endPos1;
453    
454                            if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
455                                    endPos = endPos2;
456                            }
457    
458                            if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
459                                    endPos = endPos3;
460                            }
461    
462                            if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
463                                    endPos = endPos4;
464                            }
465    
466                            if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
467                                    endPos = endPos5;
468                            }
469    
470                            if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
471                                    endPos = endPos6;
472                            }
473    
474                            if ((endPos == -1) || ((endPos7 != -1) && (endPos7 < endPos))) {
475                                    endPos = endPos7;
476                            }
477    
478                            if ((endPos == -1) || ((endPos8 != -1) && (endPos8 < endPos))) {
479                                    endPos = endPos8;
480                            }
481    
482                            if (endPos == -1) {
483                                    beginPos--;
484    
485                                    continue;
486                            }
487    
488                            String url = content.substring(beginPos + hrefLength, endPos);
489    
490                            if (!url.startsWith(privateGroupServletMapping) &&
491                                    !url.startsWith(privateUserServletMapping) &&
492                                    !url.startsWith(publicServletMapping)) {
493    
494                                    beginPos--;
495    
496                                    continue;
497                            }
498    
499                            int contextLength = 0;
500    
501                            if (Validator.isNotNull(portalContextPath)) {
502                                    contextLength = portalContextPath.length();
503                            }
504    
505                            int beginGroupPos = content.indexOf(
506                                    CharPool.SLASH, beginPos + hrefLength + contextLength + 1);
507    
508                            if (beginGroupPos == -1) {
509                                    beginPos--;
510    
511                                    continue;
512                            }
513    
514                            int endGroupPos = content.indexOf(
515                                    CharPool.SLASH, beginGroupPos + 1);
516    
517                            if (endGroupPos == -1) {
518                                    beginPos--;
519    
520                                    continue;
521                            }
522    
523                            String groupFriendlyURL = content.substring(
524                                    beginGroupPos, endGroupPos);
525    
526                            if (groupFriendlyURL.equals(group.getFriendlyURL())) {
527                                    sb.replace(
528                                            beginGroupPos, endGroupPos,
529                                            "@data_handler_group_friendly_url@");
530                            }
531    
532                            String dataHandlerServletMapping = StringPool.BLANK;
533    
534                            if (url.startsWith(privateGroupServletMapping)) {
535                                    dataHandlerServletMapping =
536                                            "@data_handler_private_group_servlet_mapping@";
537                            }
538                            else if (url.startsWith(privateUserServletMapping)) {
539                                    dataHandlerServletMapping =
540                                            "@data_handler_private_user_servlet_mapping@";
541                            }
542                            else {
543                                    dataHandlerServletMapping =
544                                            "@data_handler_public_servlet_mapping@";
545                            }
546    
547                            sb.replace(
548                                    beginPos + hrefLength, beginGroupPos,
549                                    dataHandlerServletMapping);
550    
551                            beginPos--;
552                    }
553    
554                    return sb.toString();
555            }
556    
557            protected static String exportLinksToLayout(
558                            PortletDataContext portletDataContext, String content)
559                    throws Exception {
560    
561                    List<String> oldLinksToLayout = new ArrayList<String>();
562                    List<String> newLinksToLayout = new ArrayList<String>();
563    
564                    Matcher matcher = _exportLinksToLayoutPattern.matcher(content);
565    
566                    while (matcher.find()) {
567                            long layoutId = GetterUtil.getLong(matcher.group(1));
568    
569                            String type = matcher.group(2);
570    
571                            boolean privateLayout = type.startsWith("private");
572    
573                            try {
574                                    Layout layout = LayoutLocalServiceUtil.getLayout(
575                                            portletDataContext.getScopeGroupId(), privateLayout,
576                                            layoutId);
577    
578                                    String oldLinkToLayout = matcher.group(0);
579    
580                                    StringBundler sb = new StringBundler(5);
581    
582                                    sb.append(type);
583                                    sb.append(StringPool.AT);
584                                    sb.append(layout.getUuid());
585                                    sb.append(StringPool.AT);
586                                    sb.append(layout.getFriendlyURL());
587    
588                                    String newLinkToLayout = StringUtil.replace(
589                                            oldLinkToLayout, type, sb.toString());
590    
591                                    oldLinksToLayout.add(oldLinkToLayout);
592                                    newLinksToLayout.add(newLinkToLayout);
593                            }
594                            catch (Exception e) {
595                                    if (_log.isDebugEnabled() || _log.isWarnEnabled()) {
596                                            String message =
597                                                    "Unable to get layout with ID " + layoutId +
598                                                            " in group " + portletDataContext.getScopeGroupId();
599    
600                                            if (_log.isWarnEnabled()) {
601                                                    _log.warn(message);
602                                            }
603                                            else {
604                                                    _log.debug(message, e);
605                                            }
606                                    }
607                            }
608                    }
609    
610                    content = StringUtil.replace(
611                            content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
612                            ArrayUtil.toStringArray(newLinksToLayout.toArray()));
613    
614                    return content;
615            }
616    
617            @Override
618            protected PortletPreferences doDeleteData(
619                            PortletDataContext portletDataContext, String portletId,
620                            PortletPreferences portletPreferences)
621                    throws Exception {
622    
623                    if (portletDataContext.addPrimaryKey(
624                                    DDMPortletDataHandler.class, "deleteData")) {
625    
626                            return portletPreferences;
627                    }
628    
629                    DDMTemplateLocalServiceUtil.deleteTemplates(
630                            portletDataContext.getScopeGroupId());
631    
632                    DDMStructureLocalServiceUtil.deleteStructures(
633                            portletDataContext.getScopeGroupId());
634    
635                    return portletPreferences;
636            }
637    
638            @Override
639            protected String doExportData(
640                            final PortletDataContext portletDataContext, String portletId,
641                            PortletPreferences portletPreferences)
642                    throws Exception {
643    
644                    portletDataContext.addPermissions(
645                            "com.liferay.portlet.dynamicdatamapping",
646                            portletDataContext.getScopeGroupId());
647    
648                    Element rootElement = addExportRootElement();
649    
650                    rootElement.addAttribute(
651                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
652    
653                    final Element structuresElement = rootElement.addElement("structures");
654    
655                    ActionableDynamicQuery structureActionableDynamicQuery =
656                            new DDMStructureActionableDynamicQuery() {
657    
658                                    @Override
659                                    protected void addCriteria(DynamicQuery dynamicQuery) {
660                                            portletDataContext.addDateRangeCriteria(
661                                                    dynamicQuery, "modifiedDate");
662                                    }
663    
664                                    @Override
665                                    protected void performAction(Object object)
666                                            throws PortalException {
667    
668                                            DDMStructure structure = (DDMStructure)object;
669    
670                                            StagedModelDataHandlerUtil.exportStagedModel(
671                                                    portletDataContext, structuresElement, structure);
672                                    }
673    
674                    };
675    
676                    structureActionableDynamicQuery.setGroupId(
677                            portletDataContext.getScopeGroupId());
678    
679                    structureActionableDynamicQuery.performActions();
680    
681                    final Element templatesElement = rootElement.addElement("templates");
682    
683                    ActionableDynamicQuery templateActionableDynamicQuery =
684                            new DDMTemplateActionableDynamicQuery() {
685    
686                                    @Override
687                                    protected void addCriteria(DynamicQuery dynamicQuery) {
688                                            portletDataContext.addDateRangeCriteria(
689                                                    dynamicQuery, "modifiedDate");
690                                    }
691    
692                                    @Override
693                                    protected void performAction(Object object)
694                                            throws PortalException {
695    
696                                            DDMTemplate template = (DDMTemplate)object;
697    
698                                            StagedModelDataHandlerUtil.exportStagedModel(
699                                                    portletDataContext, templatesElement, template);
700                                    }
701    
702                    };
703    
704                    templateActionableDynamicQuery.setGroupId(
705                            portletDataContext.getScopeGroupId());
706    
707                    templateActionableDynamicQuery.performActions();
708    
709                    return rootElement.formattedString();
710            }
711    
712            @Override
713            protected PortletPreferences doImportData(
714                            PortletDataContext portletDataContext, String portletId,
715                            PortletPreferences portletPreferences, String data)
716                    throws Exception {
717    
718                    portletDataContext.importPermissions(
719                            "com.liferay.portlet.dynamicdatamapping",
720                            portletDataContext.getSourceGroupId(),
721                            portletDataContext.getScopeGroupId());
722    
723                    Document document = SAXReaderUtil.read(data);
724    
725                    Element rootElement = document.getRootElement();
726    
727                    Element structuresElement = rootElement.element("structures");
728    
729                    List<Element> structureElements = structuresElement.elements(
730                            "structure");
731    
732                    for (Element structureElement : structureElements) {
733                            StagedModelDataHandlerUtil.importStagedModel(
734                                    portletDataContext, structureElement);
735                    }
736    
737                    if (portletDataContext.getBooleanParameter(NAMESPACE, "templates")) {
738                            Element templatesElement = rootElement.element("templates");
739    
740                            List<Element> templateElements = templatesElement.elements(
741                                    "template");
742    
743                            for (Element templateElement : templateElements) {
744                                    StagedModelDataHandlerUtil.importStagedModel(
745                                            portletDataContext, templateElement);
746                            }
747                    }
748    
749                    return portletPreferences;
750            }
751    
752            private static Log _log = LogFactoryUtil.getLog(
753                    DDMPortletDataHandler.class);
754    
755            private static Pattern _exportLinksToLayoutPattern = Pattern.compile(
756                    "\\[([0-9]+)@(public|private\\-[a-z]*)\\]");
757    
758    }