001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.wiki.lar;
016    
017    import com.liferay.documentlibrary.service.DLServiceUtil;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
020    import com.liferay.portal.kernel.lar.PortletDataContext;
021    import com.liferay.portal.kernel.lar.PortletDataException;
022    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
024    import com.liferay.portal.kernel.util.CharPool;
025    import com.liferay.portal.kernel.util.MapUtil;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.workflow.WorkflowConstants;
030    import com.liferay.portal.kernel.xml.Document;
031    import com.liferay.portal.kernel.xml.Element;
032    import com.liferay.portal.kernel.xml.SAXReaderUtil;
033    import com.liferay.portal.model.CompanyConstants;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.util.PortletKeys;
036    import com.liferay.portal.util.PropsUtil;
037    import com.liferay.portlet.wiki.NoSuchNodeException;
038    import com.liferay.portlet.wiki.NoSuchPageException;
039    import com.liferay.portlet.wiki.model.WikiNode;
040    import com.liferay.portlet.wiki.model.WikiPage;
041    import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
042    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
043    import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
044    import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
045    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
046    import com.liferay.portlet.wiki.util.WikiCacheUtil;
047    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
048    
049    import java.io.InputStream;
050    
051    import java.util.List;
052    import java.util.Map;
053    
054    import javax.portlet.PortletPreferences;
055    
056    /**
057     * @author Bruno Farache
058     * @author Jorge Ferrer
059     * @author Marcellus Tavares
060     * @author Juan Fernández
061     */
062    public class WikiPortletDataHandlerImpl extends BasePortletDataHandler {
063    
064            public static void exportNode(
065                            PortletDataContext context, Element nodesElement,
066                            Element pagesElement, WikiNode node)
067                    throws Exception {
068    
069                    if (context.isWithinDateRange(node.getModifiedDate())) {
070                            String path = getNodePath(context, node);
071    
072                            if (context.isPathNotProcessed(path)) {
073                                    Element nodeElement = nodesElement.addElement("node");
074    
075                                    nodeElement.addAttribute("path", path);
076    
077                                    node.setUserUuid(node.getUserUuid());
078    
079                                    context.addPermissions(WikiNode.class, node.getNodeId());
080    
081                                    context.addZipEntry(path, node);
082                            }
083                    }
084    
085                    List<WikiPage> pages = WikiPageUtil.findByN_S(
086                            node.getNodeId(), WorkflowConstants.STATUS_APPROVED,
087                            QueryUtil.ALL_POS, QueryUtil.ALL_POS,
088                            new PageVersionComparator(true));
089    
090                    for (WikiPage page : pages) {
091                            exportPage(context, nodesElement, pagesElement, page);
092                    }
093            }
094    
095            public static void importNode(PortletDataContext context, WikiNode node)
096                    throws Exception {
097    
098                    long userId = context.getUserId(node.getUserUuid());
099    
100                    ServiceContext serviceContext = new ServiceContext();
101    
102                    serviceContext.setAddCommunityPermissions(true);
103                    serviceContext.setAddGuestPermissions(true);
104                    serviceContext.setCreateDate(node.getCreateDate());
105                    serviceContext.setModifiedDate(node.getModifiedDate());
106                    serviceContext.setScopeGroupId(context.getScopeGroupId());
107    
108                    WikiNode importedNode = null;
109    
110                    if (context.isDataStrategyMirror()) {
111                            WikiNode existingNode = WikiNodeUtil.fetchByUUID_G(
112                                    node.getUuid(), context.getScopeGroupId());
113    
114                            String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
115    
116                            if ((existingNode == null) && node.getName().equals(nodeName)) {
117                                    try {
118                                            WikiNodeUtil.removeByG_N(
119                                                    context.getScopeGroupId(), node.getName());
120                                    }
121                                    catch (NoSuchNodeException nsne) {
122                                    }
123                            }
124    
125                            if (existingNode == null) {
126                                    serviceContext.setUuid(node.getUuid());
127    
128                                    importedNode = WikiNodeLocalServiceUtil.addNode(
129                                            userId, node.getName(), node.getDescription(),
130                                            serviceContext);
131                            }
132                            else {
133                                    importedNode = WikiNodeLocalServiceUtil.updateNode(
134                                            existingNode.getNodeId(), node.getName(),
135                                            node.getDescription(), serviceContext);
136                            }
137                    }
138                    else {
139                            String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
140    
141                            if (node.getName().equals(nodeName)) {
142                                    try {
143                                            WikiNodeUtil.removeByG_N(
144                                                    context.getScopeGroupId(), node.getName());
145                                    }
146                                    catch (NoSuchNodeException nsne) {
147                                    }
148                            }
149    
150                            importedNode = WikiNodeLocalServiceUtil.addNode(
151                                    userId, node.getName(), node.getDescription(), serviceContext);
152                    }
153    
154                    Map<Long, Long> nodePKs =
155                            (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
156    
157                    nodePKs.put(node.getNodeId(), importedNode.getNodeId());
158    
159                    context.importPermissions(
160                            WikiNode.class, node.getNodeId(), importedNode.getNodeId());
161            }
162    
163            public static void importPage(
164                            PortletDataContext context, Element pageElement, WikiPage page)
165                    throws Exception {
166    
167                    long userId = context.getUserId(page.getUserUuid());
168    
169                    Map<Long, Long> nodePKs =
170                            (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
171    
172                    long nodeId = MapUtil.getLong(
173                            nodePKs, page.getNodeId(), page.getNodeId());
174    
175                    long[] assetCategoryIds = null;
176                    String[] assetTagNames = null;
177    
178                    if (context.getBooleanParameter(_NAMESPACE, "categories") &&
179                            page.isHead()) {
180    
181                            assetCategoryIds = context.getAssetCategoryIds(
182                                    WikiPage.class, page.getResourcePrimKey());
183                    }
184    
185                    if (context.getBooleanParameter(_NAMESPACE, "tags") &&
186                            page.isHead()) {
187    
188                            assetTagNames = context.getAssetTagNames(
189                                    WikiPage.class, page.getResourcePrimKey());
190                    }
191    
192                    ServiceContext serviceContext = new ServiceContext();
193    
194                    serviceContext.setAddCommunityPermissions(true);
195                    serviceContext.setAddGuestPermissions(true);
196                    serviceContext.setAssetCategoryIds(assetCategoryIds);
197                    serviceContext.setAssetTagNames(assetTagNames);
198                    serviceContext.setCreateDate(page.getCreateDate());
199                    serviceContext.setModifiedDate(page.getModifiedDate());
200    
201                    if (page.getStatus() != WorkflowConstants.STATUS_APPROVED) {
202                            serviceContext.setWorkflowAction(
203                                    WorkflowConstants.ACTION_SAVE_DRAFT);
204                    }
205    
206                    WikiPage importedPage = null;
207    
208                    if (context.isDataStrategyMirror()) {
209                            WikiPage existingPage = WikiPageUtil.fetchByUUID_G(
210                                    page.getUuid(), context.getScopeGroupId());
211    
212                            if (existingPage == null) {
213                                    try {
214                                            existingPage = WikiPageLocalServiceUtil.getPage(
215                                                    nodeId, page.getTitle());
216                                    }
217                                    catch (NoSuchPageException nspe) {
218                                    }
219                            }
220    
221                            if (existingPage == null) {
222                                    serviceContext.setUuid(page.getUuid());
223    
224                                    importedPage = WikiPageLocalServiceUtil.addPage(
225                                            userId, nodeId, page.getTitle(), page.getVersion(),
226                                            page.getContent(), page.getSummary(), true,
227                                            page.getFormat(), page.getHead(), page.getParentTitle(),
228                                            page.getRedirectTitle(), serviceContext);
229                            }
230                            else {
231                                    importedPage = WikiPageLocalServiceUtil.updatePage(
232                                            userId, nodeId, existingPage.getTitle(), 0,
233                                            page.getContent(), page.getSummary(), true,
234                                            page.getFormat(), page.getParentTitle(),
235                                            page.getRedirectTitle(), serviceContext);
236                            }
237                    }
238                    else {
239                            importedPage = WikiPageLocalServiceUtil.addPage(
240                                    userId, nodeId, page.getTitle(), page.getVersion(),
241                                    page.getContent(), page.getSummary(), true, page.getFormat(),
242                                    page.getHead(), page.getParentTitle(), page.getRedirectTitle(),
243                                    serviceContext);
244                    }
245    
246                    if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
247                            page.isHead()) {
248    
249                            for (Element attachmentElement :
250                                            pageElement.elements("attachment")) {
251    
252                                    String name = attachmentElement.attributeValue("name");
253                                    String binPath = attachmentElement.attributeValue("bin-path");
254    
255                                    InputStream inputStream = context.getZipEntryAsInputStream(
256                                            binPath);
257    
258                                    WikiPageLocalServiceUtil.addPageAttachment(
259                                            importedPage.getCompanyId(),
260                                            importedPage.getAttachmentsDir(),
261                                            importedPage.getModifiedDate(), name, inputStream);
262                            }
263                    }
264    
265                    if (page.isHead()) {
266                            context.importPermissions(
267                                    WikiPage.class, page.getResourcePrimKey(),
268                                    importedPage.getResourcePrimKey());
269                    }
270    
271                    if (context.getBooleanParameter(_NAMESPACE, "comments") &&
272                            page.isHead()) {
273    
274                            context.importComments(
275                                    WikiPage.class, page.getResourcePrimKey(),
276                                    importedPage.getResourcePrimKey(), context.getScopeGroupId());
277                    }
278    
279                    if (context.getBooleanParameter(_NAMESPACE, "ratings") &&
280                            page.isHead()) {
281    
282                            context.importRatingsEntries(
283                                    WikiPage.class, page.getResourcePrimKey(),
284                                    importedPage.getResourcePrimKey());
285                    }
286            }
287    
288            public PortletDataHandlerControl[] getExportControls() {
289                    return new PortletDataHandlerControl[] {
290                            _nodesAndPages, _attachments, _categories, _comments, _ratings,
291                            _tags
292                    };
293            }
294    
295            public PortletDataHandlerControl[] getImportControls() {
296                    return new PortletDataHandlerControl[] {
297                            _nodesAndPages, _attachments, _categories, _comments, _ratings,
298                            _tags
299                    };
300            }
301    
302            public PortletPreferences importData(
303                            PortletDataContext context, String portletId,
304                            PortletPreferences preferences, String data)
305                    throws PortletDataException {
306    
307                    WikiCacheThreadLocal.setClearCache(false);
308    
309                    try {
310                            return super.importData(context, portletId, preferences, data);
311                    }
312                    finally {
313                            WikiCacheThreadLocal.setClearCache(true);
314                    }
315            }
316    
317            protected static void exportNode(
318                            PortletDataContext context, Element nodesElement, long nodeId)
319                    throws Exception {
320    
321                    if (!context.hasDateRange()) {
322                            return;
323                    }
324    
325                    WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
326    
327                    String path = getNodePath(context, node);
328    
329                    if (!context.isPathNotProcessed(path)) {
330                            return;
331                    }
332    
333                    Element nodeElement = nodesElement.addElement("node");
334    
335                    nodeElement.addAttribute("path", path);
336    
337                    node.setUserUuid(node.getUserUuid());
338    
339                    context.addPermissions(WikiNode.class, node.getNodeId());
340    
341                    context.addZipEntry(path, node);
342            }
343    
344            protected static void exportPage(
345                            PortletDataContext context, Element nodesElement,
346                            Element pagesElement, WikiPage page)
347                    throws Exception {
348    
349                    if (!context.isWithinDateRange(page.getModifiedDate())) {
350                            return;
351                    }
352    
353                    String path = getPagePath(context, page);
354    
355                    if (context.isPathNotProcessed(path)) {
356                            Element pageElement = pagesElement.addElement("page");
357    
358                            pageElement.addAttribute("path", path);
359    
360                            page.setUserUuid(page.getUserUuid());
361    
362                            context.addPermissions(WikiPage.class, page.getResourcePrimKey());
363    
364                            if (context.getBooleanParameter(_NAMESPACE, "categories") &&
365                                    page.isHead()) {
366    
367                                    context.addAssetCategories(
368                                            WikiPage.class, page.getResourcePrimKey());
369                            }
370    
371                            if (context.getBooleanParameter(_NAMESPACE, "comments") &&
372                                    page.isHead()) {
373    
374                                    context.addComments(WikiPage.class, page.getResourcePrimKey());
375                            }
376    
377                            if (context.getBooleanParameter(_NAMESPACE, "ratings") &&
378                                    page.isHead()) {
379    
380                                    context.addRatingsEntries(
381                                            WikiPage.class, page.getResourcePrimKey());
382                            }
383    
384                            if (context.getBooleanParameter(_NAMESPACE, "tags") &&
385                                    page.isHead()) {
386    
387                                    context.addAssetTags(WikiPage.class, page.getResourcePrimKey());
388                            }
389    
390                            if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
391                                    page.isHead()) {
392    
393                                    for (String attachment : page.getAttachmentsFiles()) {
394                                            int pos = attachment.lastIndexOf(CharPool.SLASH);
395    
396                                            String name = attachment.substring(pos + 1);
397                                            String binPath = getPageAttachementBinPath(
398                                                    context, page, name);
399    
400                                            Element attachmentEl = pageElement.addElement("attachment");
401    
402                                            attachmentEl.addAttribute("name", name);
403                                            attachmentEl.addAttribute("bin-path", binPath);
404    
405                                            byte[] bytes = DLServiceUtil.getFile(
406                                                    context.getCompanyId(), CompanyConstants.SYSTEM,
407                                                    attachment);
408    
409                                            context.addZipEntry(binPath, bytes);
410                                    }
411    
412                                    page.setAttachmentsDir(page.getAttachmentsDir());
413                            }
414    
415                            context.addZipEntry(path, page);
416                    }
417    
418                    exportNode(context, nodesElement, page.getNodeId());
419            }
420    
421            protected static String getNodePath(
422                    PortletDataContext context, WikiNode node) {
423    
424                    StringBundler sb = new StringBundler(4);
425    
426                    sb.append(context.getPortletPath(PortletKeys.WIKI));
427                    sb.append("/nodes/");
428                    sb.append(node.getNodeId());
429                    sb.append(".xml");
430    
431                    return sb.toString();
432            }
433    
434            protected static String getPageAttachementBinPath(
435                    PortletDataContext context, WikiPage page, String attachment) {
436    
437                    StringBundler sb = new StringBundler(5);
438    
439                    sb.append(context.getPortletPath(PortletKeys.WIKI));
440                    sb.append("/bin/");
441                    sb.append(page.getPageId());
442                    sb.append(StringPool.SLASH);
443                    sb.append(attachment);
444    
445                    return sb.toString();
446            }
447    
448            protected static String getPagePath(
449                    PortletDataContext context, WikiPage page) {
450    
451                    StringBundler sb = new StringBundler(4);
452    
453                    sb.append(context.getPortletPath(PortletKeys.WIKI));
454                    sb.append("/pages/");
455                    sb.append(page.getPageId());
456                    sb.append(".xml");
457    
458                    return sb.toString();
459            }
460    
461            protected PortletPreferences doDeleteData(
462                            PortletDataContext context, String portletId,
463                            PortletPreferences preferences)
464                    throws Exception {
465    
466                    if (!context.addPrimaryKey(
467                                    WikiPortletDataHandlerImpl.class, "deleteData")) {
468    
469                            WikiNodeLocalServiceUtil.deleteNodes(context.getScopeGroupId());
470                    }
471    
472                    return null;
473            }
474    
475            protected String doExportData(
476                            PortletDataContext context, String portletId,
477                            PortletPreferences preferences)
478                    throws Exception {
479    
480                    context.addPermissions(
481                            "com.liferay.portlet.wiki", context.getScopeGroupId());
482    
483                    Document document = SAXReaderUtil.createDocument();
484    
485                    Element rootElement = document.addElement("wiki-data");
486    
487                    rootElement.addAttribute(
488                            "group-id", String.valueOf(context.getScopeGroupId()));
489    
490                    Element nodesElement = rootElement.addElement("nodes");
491                    Element pagesElement = rootElement.addElement("pages");
492    
493                    List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
494                            context.getScopeGroupId());
495    
496                    for (WikiNode node : nodes) {
497                            exportNode(context, nodesElement, pagesElement, node);
498                    }
499    
500                    return document.formattedString();
501            }
502    
503            protected PortletPreferences doImportData(
504                            PortletDataContext context, String portletId,
505                            PortletPreferences preferences, String data)
506                    throws Exception {
507    
508                    context.importPermissions(
509                            "com.liferay.portlet.wiki", context.getSourceGroupId(),
510                            context.getScopeGroupId());
511    
512                    Document document = SAXReaderUtil.read(data);
513    
514                    Element rootElement = document.getRootElement();
515    
516                    Element nodesElement = rootElement.element("nodes");
517    
518                    for (Element nodeElement : nodesElement.elements("node")) {
519                            String path = nodeElement.attributeValue("path");
520    
521                            if (!context.isPathNotProcessed(path)) {
522                                    continue;
523                            }
524    
525                            WikiNode node = (WikiNode)context.getZipEntryAsObject(path);
526    
527                            importNode(context, node);
528                    }
529    
530                    Element pagesElement = rootElement.element("pages");
531    
532                    for (Element pageElement : pagesElement.elements("page")) {
533                            String path = pageElement.attributeValue("path");
534    
535                            if (!context.isPathNotProcessed(path)) {
536                                    continue;
537                            }
538    
539                            WikiPage page = (WikiPage)context.getZipEntryAsObject(path);
540    
541                            importPage(context, pageElement, page);
542                    }
543    
544                    Map<Long, Long> nodePKs =
545                            (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
546    
547                    for (long nodeId : nodePKs.values()) {
548                            WikiCacheUtil.clearCache(nodeId);
549                    }
550    
551                    return null;
552            }
553    
554            private static final String _NAMESPACE = "wiki";
555    
556            private static PortletDataHandlerBoolean _attachments =
557                    new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
558    
559            private static PortletDataHandlerBoolean _categories =
560                    new PortletDataHandlerBoolean(_NAMESPACE, "categories");
561    
562            private static PortletDataHandlerBoolean _comments =
563                    new PortletDataHandlerBoolean(_NAMESPACE, "comments");
564    
565            private static PortletDataHandlerBoolean _nodesAndPages =
566                    new PortletDataHandlerBoolean(
567                            _NAMESPACE, "wikis-and-pages", true, true);
568    
569            private static PortletDataHandlerBoolean _ratings =
570                    new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
571    
572            private static PortletDataHandlerBoolean _tags =
573                    new PortletDataHandlerBoolean(_NAMESPACE, "tags");
574    
575    }