1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.blogs.lar;
16  
17  import com.liferay.portal.kernel.exception.PortalException;
18  import com.liferay.portal.kernel.exception.SystemException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.StringPool;
24  import com.liferay.portal.kernel.util.Validator;
25  import com.liferay.portal.kernel.workflow.StatusConstants;
26  import com.liferay.portal.kernel.xml.Document;
27  import com.liferay.portal.kernel.xml.DocumentException;
28  import com.liferay.portal.kernel.xml.Element;
29  import com.liferay.portal.kernel.xml.Namespace;
30  import com.liferay.portal.kernel.xml.Node;
31  import com.liferay.portal.kernel.xml.SAXReaderUtil;
32  import com.liferay.portal.lar.PortletDataContext;
33  import com.liferay.portal.model.User;
34  import com.liferay.portal.service.ServiceContext;
35  import com.liferay.portal.service.UserLocalServiceUtil;
36  import com.liferay.portal.service.persistence.UserUtil;
37  import com.liferay.portal.util.PortletKeys;
38  import com.liferay.portlet.blogs.model.BlogsEntry;
39  import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
40  import com.liferay.portlet.messageboards.model.MBMessage;
41  import com.liferay.portlet.messageboards.model.MBMessageDisplay;
42  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
43  
44  import java.text.DateFormat;
45  import java.text.ParseException;
46  
47  import java.util.Calendar;
48  import java.util.Date;
49  import java.util.HashMap;
50  import java.util.List;
51  import java.util.Map;
52  import java.util.TimeZone;
53  
54  /**
55   * <a href="WordPressImporter.java.html"><b><i>View Source</i></b></a>
56   *
57   * @author Raymond Augé
58   */
59  public class WordPressImporter {
60  
61      public static void importData(PortletDataContext context)
62          throws PortalException, SystemException {
63  
64          Map<String, Long> userMap = getWordPressUserMap(context);
65  
66          String path = getWordPressPath(context, _EXPORT_FILE);
67  
68          String fileData = context.getZipEntryAsString(path);
69  
70          if (Validator.isNull(fileData)) {
71              return;
72          }
73  
74          Document wordPressDoc = null;
75  
76          try {
77              wordPressDoc = SAXReaderUtil.read(fileData);
78          }
79          catch (DocumentException de) {
80              _log.error("Reading " + path, de);
81  
82              return;
83          }
84  
85          User defaultUser = UserLocalServiceUtil.getDefaultUser(
86              context.getCompanyId());
87  
88          Element root = wordPressDoc.getRootElement();
89  
90          List<Element> entryEls = root.element("channel").elements("item");
91  
92          DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
93              _DATE_FORMAT);
94  
95          dateFormat.setTimeZone(TimeZone.getTimeZone(StringPool.UTC));
96  
97          for (Element entryEl : entryEls) {
98              importEntry(context, defaultUser, userMap, dateFormat, entryEl);
99          }
100     }
101 
102     protected static String getWordPressPath(
103         PortletDataContext context, String fileName) {
104 
105         return context.getSourcePortletPath(PortletKeys.BLOGS).concat(
106             StringPool.SLASH).concat(fileName);
107     }
108 
109     protected static Map<String, Long> getWordPressUserMap(
110         PortletDataContext context) {
111 
112         Map<String, Long> userMap = new HashMap<String, Long>();
113 
114         String path = getWordPressPath(context, _USER_MAP_FILE);
115 
116         String fileData = context.getZipEntryAsString(path);
117 
118         if (Validator.isNull(fileData)) {
119             return userMap;
120         }
121 
122         Document doc = null;
123 
124         try {
125             doc = SAXReaderUtil.read(fileData);
126         }
127         catch(DocumentException de) {
128             _log.error(de.getMessage(), de);
129 
130             return userMap;
131         }
132 
133         Element root = doc.getRootElement();
134 
135         List<Element> userEls = root.elements("wordpress-user");
136 
137         for (Element userEl : userEls) {
138             try {
139                 User user = UserUtil.findByC_EA(
140                     context.getCompanyId(),
141                     userEl.attributeValue("email-address"));
142 
143                 userMap.put(userEl.getTextTrim(), user.getUserId());
144             }
145             catch (Exception e) {
146                 if (_log.isDebugEnabled()) {
147                     _log.debug(
148                         "User for {" + context.getCompanyId() + ", " +
149                             userEl.attributeValue("email-address") + "}", e);
150                 }
151             }
152         }
153 
154         return userMap;
155     }
156 
157     protected static void importComment(
158             PortletDataContext context, User defaultUser,
159             MBMessageDisplay messageDisplay, Map<Long, Long> messageIdMap,
160             BlogsEntry entry, Element commentEl)
161         throws PortalException, SystemException {
162 
163         long commentId = GetterUtil.getLong(
164             commentEl.elementTextTrim(
165                 SAXReaderUtil.createQName("comment_id", _NS_WP)));
166 
167         String commentContent = commentEl.elementTextTrim(
168             SAXReaderUtil.createQName("comment_content", _NS_WP));
169 
170         if (Validator.isNull(commentContent)) {
171             return;
172         }
173 
174         String commentAuthor = commentEl.elementTextTrim(
175             SAXReaderUtil.createQName("comment_author", _NS_WP));
176 
177         commentAuthor = commentAuthor.substring(
178             0, Math.min(75, commentAuthor.length()));
179 
180         long commentParentId = GetterUtil.getLong(
181             commentEl.elementTextTrim(
182                 SAXReaderUtil.createQName("comment_parent", _NS_WP)));
183 
184         if (commentParentId == 0) {
185             commentParentId =
186                 messageDisplay.getMessage().getMessageId();
187         }
188         else {
189             commentParentId = messageIdMap.get(commentParentId);
190         }
191 
192         ServiceContext serviceContext = new ServiceContext();
193 
194         serviceContext.setAddCommunityPermissions(true);
195         serviceContext.setAddGuestPermissions(true);
196         serviceContext.setScopeGroupId(context.getGroupId());
197 
198         MBMessage message = MBMessageLocalServiceUtil.addDiscussionMessage(
199             defaultUser.getUserId(), commentAuthor, BlogsEntry.class.getName(),
200             entry.getEntryId(), messageDisplay.getThread().getThreadId(),
201             commentParentId, null, commentContent, serviceContext);
202 
203         messageIdMap.put(commentId, message.getMessageId());
204     }
205 
206     protected static void importEntry(
207             PortletDataContext context, User defaultUser,
208             Map<String, Long> userMap, DateFormat dateFormat, Element entryEl)
209         throws PortalException, SystemException {
210 
211         long userId = context.getUserId(null);
212 
213         String creator = entryEl.elementText(
214             SAXReaderUtil.createQName("creator", _NS_DC));
215 
216         if (userMap.containsKey(creator)) {
217             userId = userMap.get(creator);
218         }
219 
220         String title = entryEl.elementTextTrim("title");
221 
222         if (Validator.isNull(title)) {
223             title = entryEl.elementTextTrim(
224                 SAXReaderUtil.createQName("post_name", _NS_WP));
225         }
226 
227         String content = entryEl.elementText(
228             SAXReaderUtil.createQName("encoded", _NS_CONTENT));
229 
230         content = content.replaceAll("\\n", "\n<br />");
231 
232         // LPS-1425
233 
234         if (Validator.isNull(content)) {
235             content = "<br />";
236         }
237 
238         String dateText = entryEl.elementTextTrim(
239             SAXReaderUtil.createQName("post_date_gmt", _NS_WP));
240 
241         Date postDate = new Date();
242 
243         try {
244             postDate = dateFormat.parse(dateText);
245         }
246         catch (ParseException pe) {
247             _log.warn("Parse " + dateText, pe);
248         }
249 
250         Calendar cal = Calendar.getInstance();
251 
252         cal.setTime(postDate);
253 
254         int displayDateMonth = cal.get(Calendar.MONTH);
255         int displayDateDay = cal.get(Calendar.DAY_OF_MONTH);
256         int displayDateYear = cal.get(Calendar.YEAR);
257         int displayDateHour = cal.get(Calendar.HOUR_OF_DAY);
258         int displayDateMinute = cal.get(Calendar.MINUTE);
259 
260         String statusText = entryEl.elementTextTrim(
261             SAXReaderUtil.createQName("status", _NS_WP));
262 
263         int status = StatusConstants.APPROVED;
264 
265         if (statusText.equalsIgnoreCase("draft")) {
266             status = StatusConstants.DRAFT;
267         }
268 
269         String pingStatusText = entryEl.elementTextTrim(
270             SAXReaderUtil.createQName("ping_status", _NS_WP));
271 
272         boolean allowPingbacks = pingStatusText.equalsIgnoreCase("open");
273         boolean allowTrackbacks = allowPingbacks;
274 
275         String[] assetTagNames = null;
276 
277         String categoryText = entryEl.elementTextTrim("category");
278 
279         if (Validator.isNotNull(categoryText)) {
280             assetTagNames = new String[] {categoryText};
281         }
282 
283         ServiceContext serviceContext = new ServiceContext();
284 
285         serviceContext.setAddCommunityPermissions(true);
286         serviceContext.setAddGuestPermissions(true);
287         serviceContext.setAssetTagNames(assetTagNames);
288         serviceContext.setScopeGroupId(context.getGroupId());
289         serviceContext.setStatus(status);
290 
291         BlogsEntry entry = null;
292 
293         try {
294             entry = BlogsEntryLocalServiceUtil.addEntry(
295                 null, userId, title, content, displayDateMonth, displayDateDay,
296                 displayDateYear, displayDateHour, displayDateMinute,
297                 allowPingbacks, allowTrackbacks, null, serviceContext);
298         }
299         catch (Exception e) {
300             _log.error("Add entry " + title, e);
301 
302             return;
303         }
304 
305         MBMessageDisplay messageDisplay =
306             MBMessageLocalServiceUtil.getDiscussionMessageDisplay(
307                 userId, BlogsEntry.class.getName(), entry.getEntryId(),
308                 StatusConstants.APPROVED);
309 
310         Map<Long, Long> messageIdMap = new HashMap<Long, Long>();
311 
312         List<Node> commentNodes = entryEl.selectNodes(
313             "wp:comment", "wp:comment_parent/text()");
314 
315         for (Node commentNode : commentNodes) {
316             Element commentEl = (Element)commentNode;
317 
318             importComment(
319                 context, defaultUser, messageDisplay, messageIdMap, entry,
320                 commentEl);
321         }
322     }
323 
324     private static final String _DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
325 
326     private static final String _EXPORT_FILE = "wordpress.xml";
327 
328     private static final Namespace _NS_CONTENT = SAXReaderUtil.createNamespace(
329         "content", "http://purl.org/rss/1.0/modules/content/");
330 
331     private static final Namespace _NS_DC = SAXReaderUtil.createNamespace(
332         "dc", "http://purl.org/dc/elements/1.1/");
333 
334     private static final Namespace _NS_WP = SAXReaderUtil.createNamespace(
335         "wp", "http://wordpress.org/export/1.0/");
336 
337     private static final String _USER_MAP_FILE = "wordpress-user-map.xml";
338 
339     private static Log _log = LogFactoryUtil.getLog(WordPressImporter.class);
340 
341 }