1
14
15 package com.liferay.portal.lar;
16
17 import com.liferay.portal.LARFileException;
18 import com.liferay.portal.LARTypeException;
19 import com.liferay.portal.LayoutImportException;
20 import com.liferay.portal.PortalException;
21 import com.liferay.portal.PortletIdException;
22 import com.liferay.portal.SystemException;
23 import com.liferay.portal.kernel.log.Log;
24 import com.liferay.portal.kernel.log.LogFactoryUtil;
25 import com.liferay.portal.kernel.util.GetterUtil;
26 import com.liferay.portal.kernel.util.MapUtil;
27 import com.liferay.portal.kernel.util.ReleaseInfo;
28 import com.liferay.portal.kernel.util.StringUtil;
29 import com.liferay.portal.kernel.xml.Document;
30 import com.liferay.portal.kernel.xml.DocumentException;
31 import com.liferay.portal.kernel.xml.Element;
32 import com.liferay.portal.kernel.xml.SAXReaderUtil;
33 import com.liferay.portal.kernel.zip.ZipReader;
34 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
35 import com.liferay.portal.model.Layout;
36 import com.liferay.portal.model.Portlet;
37 import com.liferay.portal.model.PortletConstants;
38 import com.liferay.portal.model.PortletItem;
39 import com.liferay.portal.model.PortletPreferences;
40 import com.liferay.portal.model.User;
41 import com.liferay.portal.service.LayoutLocalServiceUtil;
42 import com.liferay.portal.service.PortletItemLocalServiceUtil;
43 import com.liferay.portal.service.PortletLocalServiceUtil;
44 import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
45 import com.liferay.portal.service.UserLocalServiceUtil;
46 import com.liferay.portal.service.persistence.PortletPreferencesUtil;
47 import com.liferay.portal.service.persistence.UserUtil;
48 import com.liferay.portal.util.PortletKeys;
49 import com.liferay.portlet.PortletPreferencesImpl;
50 import com.liferay.portlet.PortletPreferencesSerializer;
51 import com.liferay.portlet.messageboards.model.MBMessage;
52 import com.liferay.portlet.ratings.model.RatingsEntry;
53 import com.liferay.portlet.social.util.SocialActivityThreadLocal;
54
55 import java.io.File;
56
57 import java.util.ArrayList;
58 import java.util.HashSet;
59 import java.util.List;
60 import java.util.Map;
61
62 import org.apache.commons.lang.time.StopWatch;
63
64
74 public class PortletImporter {
75
76 public void importPortletInfo(
77 long userId, long plid, long groupId, String portletId,
78 Map<String, String[]> parameterMap, File file)
79 throws PortalException, SystemException {
80
81 boolean deletePortletData = MapUtil.getBoolean(
82 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
83 boolean importPortletData = MapUtil.getBoolean(
84 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
85 boolean importPortletArchivedSetups = MapUtil.getBoolean(
86 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
87 boolean importPortletSetup = MapUtil.getBoolean(
88 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
89 boolean importUserPreferences = MapUtil.getBoolean(
90 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
91 String userIdStrategy = MapUtil.getString(
92 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
93
94 StopWatch stopWatch = null;
95
96 if (_log.isInfoEnabled()) {
97 stopWatch = new StopWatch();
98
99 stopWatch.start();
100 }
101
102 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
103
104 long companyId = layout.getCompanyId();
105
106 User user = UserUtil.findByPrimaryKey(userId);
107
108 UserIdStrategy strategy = getUserIdStrategy(user, userIdStrategy);
109
110 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
111
112 PortletDataContext context = new PortletDataContextImpl(
113 companyId, groupId, parameterMap, new HashSet<String>(), strategy,
114 zipReader);
115
116 context.setPlid(plid);
117
118
120 Element root = null;
121
122
124 String xml = context.getZipEntryAsString("/manifest.xml");
125
126 try {
127 Document doc = SAXReaderUtil.read(xml);
128
129 root = doc.getRootElement();
130 }
131 catch (Exception e) {
132 throw new LARFileException(
133 "Cannot locate a manifest in this LAR file.");
134 }
135
136
138 Element header = root.element("header");
139
140 int buildNumber = ReleaseInfo.getBuildNumber();
141
142 int importBuildNumber = GetterUtil.getInteger(
143 header.attributeValue("build-number"));
144
145 if (buildNumber != importBuildNumber) {
146 throw new LayoutImportException(
147 "LAR build number " + importBuildNumber + " does not match " +
148 "portal build number " + buildNumber);
149 }
150
151
153 String type = header.attributeValue("type");
154
155 if (!type.equals("portlet")) {
156 throw new LARTypeException(
157 "Invalid type of LAR file (" + type + ")");
158 }
159
160
162 String rootPortletId = header.attributeValue("root-portlet-id");
163
164 if (!PortletConstants.getRootPortletId(portletId).equals(
165 rootPortletId)) {
166
167 throw new PortletIdException("Invalid portlet id " + rootPortletId);
168 }
169
170
172 long importGroupId = GetterUtil.getLong(
173 header.attributeValue("group-id"));
174
175 context.setImportGroupId(importGroupId);
176
177
180 readComments(context, root);
181 readRatings(context, root);
182 readTags(context, root);
183
184
186 if (_log.isDebugEnabled()) {
187 _log.debug("Deleting portlet data");
188 }
189
190 if (deletePortletData) {
191 deletePortletData(context, portletId, plid);
192 }
193
194 Element portletRefEl = root.element("portlet");
195 Element portletEl = null;
196
197 try {
198 Document portletDoc = SAXReaderUtil.read(
199 context.getZipEntryAsString(
200 portletRefEl.attributeValue("path")));
201
202 portletEl = portletDoc.getRootElement();
203 }
204 catch (DocumentException de) {
205 throw new SystemException(de);
206 }
207
208
210 importPortletPreferences(
211 context, layout.getCompanyId(), groupId, plid, portletId, portletEl,
212 importPortletSetup, importPortletArchivedSetups,
213 importUserPreferences);
214
215
217 if (_log.isDebugEnabled()) {
218 _log.debug("Importing portlet data");
219 }
220
221 if (importPortletData) {
222 Element portletDataRefEl = portletEl.element("portlet-data");
223
224 if (portletDataRefEl != null) {
225 importPortletData(
226 context, portletId, plid, portletDataRefEl);
227 }
228 else {
229 _log.warn(
230 "Could not import portlet data because it cannot be " +
231 "found in the input");
232 }
233 }
234
235 if (_log.isInfoEnabled()) {
236 _log.info(
237 "Importing portlet data takes " + stopWatch.getTime() + " ms");
238 }
239
240 zipReader.close();
241 }
242
243 protected void deletePortletData(
244 PortletDataContext context, String portletId, long plid)
245 throws SystemException {
246
247 long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
248 int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
249
250 PortletPreferences portletPreferences =
251 PortletPreferencesUtil.fetchByO_O_P_P(
252 ownerId, ownerType, plid, portletId);
253
254 if (portletPreferences == null) {
255 portletPreferences =
256 new com.liferay.portal.model.impl.PortletPreferencesImpl();
257 }
258
259 String xml = deletePortletData(
260 context, portletId, portletPreferences);
261
262 if (xml != null) {
263 PortletPreferencesLocalServiceUtil.updatePreferences(
264 ownerId, ownerType, plid, portletId, xml);
265 }
266 }
267
268 protected String deletePortletData(
269 PortletDataContext context, String portletId,
270 PortletPreferences portletPreferences)
271 throws SystemException {
272
273 Portlet portlet = PortletLocalServiceUtil.getPortletById(
274 context.getCompanyId(), portletId);
275
276 if (portlet == null) {
277 if (_log.isDebugEnabled()) {
278 _log.debug(
279 "Do not delete portlet data for " + portletId +
280 " because the portlet does not exist");
281 }
282
283 return null;
284 }
285
286 PortletDataHandler portletDataHandler =
287 portlet.getPortletDataHandlerInstance();
288
289 if (portletDataHandler == null) {
290 if (_log.isDebugEnabled()) {
291 _log.debug(
292 "Do not delete portlet data for " + portletId +
293 " because the portlet does not have a " +
294 "PortletDataHandler");
295 }
296
297 return null;
298 }
299
300 if (_log.isDebugEnabled()) {
301 _log.debug("Deleting data for " + portletId);
302 }
303
304 PortletPreferencesImpl prefsImpl =
305 (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
306 portletPreferences.getPreferences());
307
308 try {
309 prefsImpl =
310 (PortletPreferencesImpl)portletDataHandler.deleteData(
311 context, portletId, prefsImpl);
312 }
313 catch (Exception e) {
314 throw new SystemException(e);
315 }
316
317 if (prefsImpl == null) {
318 return null;
319 }
320
321 return PortletPreferencesSerializer.toXML(prefsImpl);
322 }
323
324 protected UserIdStrategy getUserIdStrategy(
325 User user, String userIdStrategy) {
326
327 if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
328 return new AlwaysCurrentUserIdStrategy(user);
329 }
330
331 return new CurrentUserIdStrategy(user);
332 }
333
334 protected void importPortletData(
335 PortletDataContext context, String portletId, long plid,
336 Element portletDataRefEl)
337 throws SystemException {
338
339 long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
340 int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
341
342 PortletPreferences portletPreferences =
343 PortletPreferencesUtil.fetchByO_O_P_P(
344 ownerId, ownerType, plid, portletId);
345
346 if (portletPreferences == null) {
347 portletPreferences =
348 new com.liferay.portal.model.impl.PortletPreferencesImpl();
349 }
350
351 String xml = importPortletData(
352 context, portletId, portletPreferences, portletDataRefEl);
353
354 if (xml != null) {
355 PortletPreferencesLocalServiceUtil.updatePreferences(
356 ownerId, ownerType, plid, portletId, xml);
357 }
358 }
359
360 protected String importPortletData(
361 PortletDataContext context, String portletId,
362 PortletPreferences portletPreferences, Element portletDataRefEl)
363 throws SystemException {
364
365 Portlet portlet = PortletLocalServiceUtil.getPortletById(
366 context.getCompanyId(), portletId);
367
368 if (portlet == null) {
369 if (_log.isDebugEnabled()) {
370 _log.debug(
371 "Do not import portlet data for " + portletId +
372 " because the portlet does not exist");
373 }
374
375 return null;
376 }
377
378 PortletDataHandler portletDataHandler =
379 portlet.getPortletDataHandlerInstance();
380
381 if (portletDataHandler == null) {
382 if (_log.isDebugEnabled()) {
383 _log.debug(
384 "Do not import portlet data for " + portletId +
385 " because the portlet does not have a " +
386 "PortletDataHandler");
387 }
388
389 return null;
390 }
391
392 if (_log.isDebugEnabled()) {
393 _log.debug("Importing data for " + portletId);
394 }
395
396 PortletPreferencesImpl prefsImpl = null;
397
398 if (portletPreferences != null) {
399 prefsImpl = (PortletPreferencesImpl)
400 PortletPreferencesSerializer.fromDefaultXML(
401 portletPreferences.getPreferences());
402 }
403
404 String portletData = context.getZipEntryAsString(
405 portletDataRefEl.attributeValue("path"));
406
407 try {
408 SocialActivityThreadLocal.setEnabled(false);
409
410 prefsImpl =
411 (PortletPreferencesImpl)portletDataHandler.importData(
412 context, portletId, prefsImpl, portletData);
413 }
414 catch (Exception e) {
415 throw new SystemException(e);
416 }
417 finally {
418 SocialActivityThreadLocal.setEnabled(true);
419 }
420
421 if (prefsImpl == null) {
422 return null;
423 }
424
425 return PortletPreferencesSerializer.toXML(prefsImpl);
426 }
427
428 protected void importPortletPreferences(
429 PortletDataContext context, long companyId, long groupId, long plid,
430 String portletId, Element parentEl, boolean importPortletSetup,
431 boolean importPortletArchivedSetups, boolean importUserPreferences)
432 throws PortalException, SystemException {
433
434 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
435
436 List<Element> prefsEls = parentEl.elements("portlet-preferences");
437
438 for (Element prefEl : prefsEls) {
439 String path = prefEl.attributeValue("path");
440
441 if (context.isPathNotProcessed(path)) {
442 Element el = null;
443 String xml = null;
444
445 try {
446 xml = context.getZipEntryAsString(path);
447
448 Document prefsDoc = SAXReaderUtil.read(xml);
449
450 el = prefsDoc.getRootElement();
451 }
452 catch (DocumentException de) {
453 throw new SystemException(de);
454 }
455
456 long ownerId = GetterUtil.getLong(
457 el.attributeValue("owner-id"));
458 int ownerType = GetterUtil.getInteger(
459 el.attributeValue("owner-type"));
460
461 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
462 continue;
463 }
464
465 if (((ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
466 (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) &&
467 !importPortletSetup) {
468
469 continue;
470 }
471
472 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) &&
473 !importPortletArchivedSetups) {
474
475 continue;
476 }
477
478 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
479 (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
480 !importUserPreferences) {
481
482 continue;
483 }
484
485 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
486 plid = PortletKeys.PREFS_PLID_SHARED;
487 ownerId = context.getGroupId();
488 }
489
490 boolean defaultUser = GetterUtil.getBoolean(
491 el.attributeValue("default-user"));
492
493 if (portletId == null) {
494 portletId = el.attributeValue("portlet-id");
495 }
496
497 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
498 portletId = PortletConstants.getRootPortletId(portletId);
499
500 String userUuid = el.attributeValue("archive-user-uuid");
501 String name = el.attributeValue("archive-name");
502
503 long userId = context.getUserId(userUuid);
504
505 PortletItem portletItem =
506 PortletItemLocalServiceUtil.updatePortletItem(
507 userId, groupId, name, portletId,
508 PortletPreferences.class.getName());
509
510 plid = 0;
511 ownerId = portletItem.getPortletItemId();
512 }
513
514 if (defaultUser) {
515 ownerId = defaultUserId;
516 }
517
518 PortletPreferencesLocalServiceUtil.updatePreferences(
519 ownerId, ownerType, plid, portletId, xml);
520 }
521 }
522 }
523
524 protected void readComments(PortletDataContext context, Element parentEl)
525 throws SystemException {
526
527 try {
528 String xml = context.getZipEntryAsString(
529 context.getImportRootPath() + "/comments.xml");
530
531 Document doc = SAXReaderUtil.read(xml);
532
533 Element root = doc.getRootElement();
534
535 List<Element> assets = root.elements("asset");
536
537 for (Element asset : assets) {
538 String path = asset.attributeValue("path");
539 String className = asset.attributeValue("class-name");
540 long classPK = GetterUtil.getLong(
541 asset.attributeValue("class-pk"));
542
543 List<String> zipFolderEntries = context.getZipFolderEntries(
544 path);
545
546 List<MBMessage> messages = new ArrayList<MBMessage>();
547
548 for (String zipFolderEntry : zipFolderEntries) {
549 MBMessage message = (MBMessage)context.getZipEntryAsObject(
550 zipFolderEntry);
551
552 if (message != null) {
553 messages.add(message);
554 }
555 }
556
557 context.addComments(className, classPK, messages);
558 }
559 }
560 catch (Exception e) {
561 throw new SystemException(e);
562 }
563 }
564
565 protected void readRatings(PortletDataContext context, Element parentEl)
566 throws SystemException {
567
568 try {
569 String xml = context.getZipEntryAsString(
570 context.getImportRootPath() + "/ratings.xml");
571
572 Document doc = SAXReaderUtil.read(xml);
573
574 Element root = doc.getRootElement();
575
576 List<Element> assets = root.elements("asset");
577
578 for (Element asset : assets) {
579 String path = asset.attributeValue("path");
580 String className = asset.attributeValue("class-name");
581 long classPK = GetterUtil.getLong(
582 asset.attributeValue("class-pk"));
583
584 List<String> zipFolderEntries = context.getZipFolderEntries(
585 path);
586
587 List<RatingsEntry> ratingsEntries =
588 new ArrayList<RatingsEntry>();
589
590 for (String zipFolderEntry : zipFolderEntries) {
591 RatingsEntry ratingsEntry =
592 (RatingsEntry)context.getZipEntryAsObject(
593 zipFolderEntry);
594
595 if (ratingsEntry != null) {
596 ratingsEntries.add(ratingsEntry);
597 }
598 }
599
600 context.addRatingsEntries(
601 className, new Long(classPK), ratingsEntries);
602 }
603 }
604 catch (Exception e) {
605 throw new SystemException(e);
606 }
607 }
608
609 protected void readTags(PortletDataContext context, Element parentEl)
610 throws SystemException {
611
612 try {
613 String xml = context.getZipEntryAsString(
614 context.getImportRootPath() + "/tags.xml");
615
616 Document doc = SAXReaderUtil.read(xml);
617
618 Element root = doc.getRootElement();
619
620 List<Element> assets = root.elements("asset");
621
622 for (Element asset : assets) {
623 String className = GetterUtil.getString(
624 asset.attributeValue("class-name"));
625 long classPK = GetterUtil.getLong(
626 asset.attributeValue("class-pk"));
627 String entries = GetterUtil.getString(
628 asset.attributeValue("entries"));
629
630 context.addTagsEntries(
631 className, new Long(classPK),
632 StringUtil.split(entries, ","));
633 }
634 }
635 catch (Exception e) {
636 throw new SystemException(e);
637 }
638 }
639
640 private static Log _log = LogFactoryUtil.getLog(PortletImporter.class);
641
642 }