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