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