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.lar.PortletDataContext;
34 import com.liferay.portal.kernel.lar.PortletDataHandler;
35 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
36 import com.liferay.portal.kernel.lar.UserIdStrategy;
37 import com.liferay.portal.kernel.util.GetterUtil;
38 import com.liferay.portal.kernel.util.ObjectValuePair;
39 import com.liferay.portal.kernel.util.ReleaseInfo;
40 import com.liferay.portal.kernel.util.StringUtil;
41 import com.liferay.portal.kernel.zip.ZipReader;
42 import com.liferay.portal.model.Layout;
43 import com.liferay.portal.model.Portlet;
44 import com.liferay.portal.model.PortletConstants;
45 import com.liferay.portal.model.PortletItem;
46 import com.liferay.portal.model.PortletPreferences;
47 import com.liferay.portal.model.User;
48 import com.liferay.portal.service.LayoutLocalServiceUtil;
49 import com.liferay.portal.service.PortletItemLocalServiceUtil;
50 import com.liferay.portal.service.PortletLocalServiceUtil;
51 import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
52 import com.liferay.portal.service.UserLocalServiceUtil;
53 import com.liferay.portal.service.persistence.PortletPreferencesUtil;
54 import com.liferay.portal.service.persistence.UserUtil;
55 import com.liferay.portal.util.DocumentUtil;
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.util.MapUtil;
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 import org.apache.commons.logging.Log;
72 import org.apache.commons.logging.LogFactory;
73
74 import org.dom4j.Document;
75 import org.dom4j.DocumentException;
76 import org.dom4j.Element;
77
78
89 public class PortletImporter {
90
91 public void importPortletInfo(
92 long userId, long plid, String portletId,
93 Map<String, String[]> parameterMap, InputStream is)
94 throws PortalException, SystemException {
95
96 boolean deletePortletData = MapUtil.getBoolean(
97 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
98 boolean importPortletData = MapUtil.getBoolean(
99 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
100 boolean importPortletArchivedSetups = MapUtil.getBoolean(
101 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
102 boolean importPortletSetup = MapUtil.getBoolean(
103 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
104 boolean importUserPreferences = MapUtil.getBoolean(
105 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
106 String userIdStrategy = MapUtil.getString(
107 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
108
109 StopWatch stopWatch = null;
110
111 if (_log.isInfoEnabled()) {
112 stopWatch = new StopWatch();
113
114 stopWatch.start();
115 }
116
117 Layout layout = LayoutLocalServiceUtil.getLayout(plid);
118
119 long companyId = layout.getCompanyId();
120
121 User user = UserUtil.findByPrimaryKey(userId);
122
123 UserIdStrategy strategy = getUserIdStrategy(user, userIdStrategy);
124
125 ZipReader zipReader = new ZipReader(is);
126
127 PortletDataContext context = new PortletDataContextImpl(
128 companyId, layout.getGroupId(), parameterMap, new HashSet(),
129 strategy, zipReader);
130
131 context.setPlid(plid);
132
133
135 Element root = null;
136
137
139 String xml = context.getZipEntryAsString("/manifest.xml");
140
141 try {
142 Document doc = DocumentUtil.readDocumentFromXML(xml);
143
144 root = doc.getRootElement();
145 }
146 catch (Exception e) {
147 throw new LARFileException(
148 "Cannot locate a manifest in this LAR file.");
149 }
150
151
153 Element header = root.element("header");
154
155 int buildNumber = ReleaseInfo.getBuildNumber();
156
157 int importBuildNumber = GetterUtil.getInteger(
158 header.attributeValue("build-number"));
159
160 if (buildNumber != importBuildNumber) {
161 throw new LayoutImportException(
162 "LAR build number " + importBuildNumber + " does not match " +
163 "portal build number " + buildNumber);
164 }
165
166
168 String type = header.attributeValue("type");
169
170 if (!type.equals("portlet")) {
171 throw new LARTypeException(
172 "Invalid type of LAR file (" + type + ")");
173 }
174
175
177 String rootPortletId = header.attributeValue("root-portlet-id");
178
179 if (!PortletConstants.getRootPortletId(portletId).equals(
180 rootPortletId)) {
181
182 throw new PortletIdException("Invalid portlet id " + rootPortletId);
183 }
184
185
187 long importGroupId = GetterUtil.getLong(
188 header.attributeValue("group-id"));
189
190 context.setImportGroupId(importGroupId);
191
192
195 readComments(context, root);
196 readRatings(context, root);
197 readTags(context, root);
198
199
201 if (_log.isDebugEnabled()) {
202 _log.debug("Deleting portlet data");
203 }
204
205 if (deletePortletData) {
206 deletePortletData(context, portletId, plid);
207 }
208
209 Element portletRefEl = root.element("portlet");
210 Element portletEl = null;
211
212 try {
213 Document portletDoc = DocumentUtil.readDocumentFromXML(
214 context.getZipEntryAsString(
215 portletRefEl.attributeValue("path")));
216
217 portletEl = portletDoc.getRootElement();
218 }
219 catch (DocumentException de) {
220 throw new SystemException(de);
221 }
222
223
225 importPortletPreferences(
226 context, layout.getCompanyId(), layout.getGroupId(), plid,
227 portletId, portletEl, importPortletSetup,
228 importPortletArchivedSetups, importUserPreferences);
229
230
232 if (_log.isDebugEnabled()) {
233 _log.debug("Importing portlet data");
234 }
235
236 if (importPortletData) {
237 importPortletData(
238 context, portletId, plid, portletEl.element("portlet-data"));
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 PortalException, SystemException {
250
251 try {
252 PortletPreferences portletPreferences =
253 PortletPreferencesUtil.findByO_O_P_P(
254 PortletKeys.PREFS_OWNER_ID_DEFAULT,
255 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, plid,
256 portletId);
257
258 String preferences = deletePortletData(
259 context, portletId, portletPreferences);
260
261 if (preferences != null) {
262 portletPreferences.setPreferences(preferences);
263
264 PortletPreferencesUtil.update(portletPreferences, false);
265 }
266 }
267 catch (NoSuchPortletPreferencesException nsppe) {
268 }
269 }
270
271 protected String deletePortletData(
272 PortletDataContext context, String portletId,
273 PortletPreferences portletPreferences)
274 throws PortalException, SystemException {
275
276 Portlet portlet = PortletLocalServiceUtil.getPortletById(
277 context.getCompanyId(), portletId);
278
279 if (portlet == null) {
280 if (_log.isDebugEnabled()) {
281 _log.debug(
282 "Do not delete portlet data for " + portletId +
283 " because the portlet does not exist");
284 }
285
286 return null;
287 }
288
289 PortletDataHandler portletDataHandler =
290 portlet.getPortletDataHandlerInstance();
291
292 if (portletDataHandler == null) {
293 if (_log.isDebugEnabled()) {
294 _log.debug(
295 "Do not delete portlet data for " + portletId +
296 " because the portlet does not have a " +
297 "PortletDataHandler");
298 }
299
300 return null;
301 }
302
303 if (_log.isDebugEnabled()) {
304 _log.debug("Deleting data for " + portletId);
305 }
306
307 PortletPreferencesImpl prefsImpl =
308 (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
309 portletPreferences.getPreferences());
310
311 prefsImpl = (PortletPreferencesImpl)portletDataHandler.deleteData(
312 context, portletId, prefsImpl);
313
314 if (prefsImpl == null) {
315 return null;
316 }
317
318 return PortletPreferencesSerializer.toXML(prefsImpl);
319 }
320
321 protected UserIdStrategy getUserIdStrategy(
322 User user, String userIdStrategy) {
323
324 if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
325 return new AlwaysCurrentUserIdStrategy(user);
326 }
327
328 return new CurrentUserIdStrategy(user);
329 }
330
331 protected void importPortletData(
332 PortletDataContext context, String portletId, long plid,
333 Element portletDataRefEl)
334 throws PortalException, SystemException {
335
336 try {
337 PortletPreferences portletPreferences =
338 PortletPreferencesUtil.findByO_O_P_P(
339 PortletKeys.PREFS_OWNER_ID_DEFAULT,
340 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, plid,
341 portletId);
342
343 String preferences = importPortletData(
344 context, portletId, portletPreferences, portletDataRefEl);
345
346 if (preferences != null) {
347 portletPreferences.setPreferences(preferences);
348
349 PortletPreferencesUtil.update(portletPreferences, false);
350 }
351 }
352 catch (NoSuchPortletPreferencesException nsppe) {
353 }
354 }
355
356 protected String importPortletData(
357 PortletDataContext context, String portletId,
358 PortletPreferences portletPreferences, Element portletDataRefEl)
359 throws PortalException, SystemException {
360
361 Portlet portlet = PortletLocalServiceUtil.getPortletById(
362 context.getCompanyId(), portletId);
363
364 if (portlet == null) {
365 if (_log.isDebugEnabled()) {
366 _log.debug(
367 "Do not import portlet data for " + portletId +
368 " because the portlet does not exist");
369 }
370
371 return null;
372 }
373
374 PortletDataHandler portletDataHandler =
375 portlet.getPortletDataHandlerInstance();
376
377 if (portletDataHandler == null) {
378 if (_log.isDebugEnabled()) {
379 _log.debug(
380 "Do not import portlet data for " + portletId +
381 " because the portlet does not have a " +
382 "PortletDataHandler");
383 }
384
385 return null;
386 }
387
388 if (_log.isDebugEnabled()) {
389 _log.debug("Importing data for " + portletId);
390 }
391
392 PortletPreferencesImpl prefsImpl = null;
393
394 if (portletPreferences != null) {
395 prefsImpl = (PortletPreferencesImpl)
396 PortletPreferencesSerializer.fromDefaultXML(
397 portletPreferences.getPreferences());
398 }
399
400 String portletData = context.getZipEntryAsString(
401 portletDataRefEl.attributeValue("path"));
402
403 prefsImpl = (PortletPreferencesImpl)portletDataHandler.importData(
404 context, portletId, prefsImpl, portletData);
405
406 if (prefsImpl == null) {
407 return null;
408 }
409
410 return PortletPreferencesSerializer.toXML(prefsImpl);
411 }
412
413 protected void importPortletPreferences(
414 PortletDataContext context, long companyId, long groupId, long plid,
415 String portletId, Element parentEl, boolean importPortletSetup,
416 boolean importPortletArchivedSetups, boolean importUserPreferences)
417 throws PortalException, SystemException {
418
419 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
420
421 List<Element> prefsEls = parentEl.elements("portlet-preference");
422
423 for (Element prefEl : prefsEls) {
424 String path = prefEl.attributeValue("path");
425
426 if (context.isPathNotProcessed(path)) {
427
428 Element el = null;
429 String preferences = null;
430
431 try {
432 preferences = context.getZipEntryAsString(path);
433
434 Document prefsDoc = DocumentUtil.readDocumentFromXML(
435 preferences);
436
437 el = prefsDoc.getRootElement();
438 }
439 catch (DocumentException de) {
440 throw new SystemException(de);
441 }
442
443 long ownerId = GetterUtil.getLong(
444 el.attributeValue("owner-id"));
445 int ownerType = GetterUtil.getInteger(
446 el.attributeValue("owner-type"));
447
448 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
449 continue;
450 }
451
452 if (((ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
453 (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) &&
454 !importPortletSetup) {
455
456 continue;
457 }
458
459 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) &&
460 !importPortletArchivedSetups) {
461
462 continue;
463 }
464
465 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
466 (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
467 !importUserPreferences) {
468
469 continue;
470 }
471
472 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
473 plid = PortletKeys.PREFS_PLID_SHARED;
474 ownerId = context.getGroupId();
475 }
476
477 boolean defaultUser = GetterUtil.getBoolean(
478 el.attributeValue("default-user"));
479
480 if (portletId == null) {
481 portletId = el.attributeValue("portlet-id");
482 }
483
484 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
485 String userUuid = el.attributeValue("archive-user-uuid");
486 String name = el.attributeValue("archive-name");
487
488 long userId = context.getUserId(userUuid);
489
490 PortletItem portletItem =
491 PortletItemLocalServiceUtil.updatePortletItem(
492 userId, groupId, name, portletId,
493 PortletPreferences.class.getName());
494
495 plid = 0;
496 ownerId = portletItem.getPortletItemId();
497 }
498
499 if (defaultUser) {
500 ownerId = defaultUserId;
501 }
502
503 PortletPreferences prefs =
504 PortletPreferencesUtil.fetchByO_O_P_P(
505 ownerId, ownerType, plid, portletId);
506
507 if (prefs != null) {
508 PortletPreferencesLocalServiceUtil.deletePortletPreferences(
509 ownerId, ownerType, plid, portletId);
510 }
511
512 long portletPreferencesId = CounterLocalServiceUtil.increment();
513
514 PortletPreferences portletPreferences =
515 PortletPreferencesUtil.create(portletPreferencesId);
516
517 portletPreferences.setOwnerId(ownerId);
518 portletPreferences.setOwnerType(ownerType);
519 portletPreferences.setPlid(plid);
520 portletPreferences.setPortletId(portletId);
521
522 portletPreferences.setPreferences(preferences);
523
524 PortletPreferencesUtil.update(portletPreferences, true);
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 = DocumentUtil.readDocumentFromXML(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, new Long(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 = DocumentUtil.readDocumentFromXML(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 = DocumentUtil.readDocumentFromXML(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 = LogFactory.getLog(PortletImporter.class);
644
645 }