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