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