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