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(el.attributeValue("owner-id"));
444 int ownerType = GetterUtil.getInteger(
445 el.attributeValue("owner-type"));
446
447 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
448 continue;
449 }
450
451 if (((ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
452 (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) &&
453 !importPortletSetup) {
454
455 continue;
456 }
457
458 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) &&
459 !importPortletArchivedSetups) {
460
461 continue;
462 }
463
464 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
465 (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
466 !importUserPreferences) {
467
468 continue;
469 }
470
471 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
472 plid = PortletKeys.PREFS_PLID_SHARED;
473 ownerId = context.getGroupId();
474 }
475
476 boolean defaultUser = GetterUtil.getBoolean(
477 el.attributeValue("default-user"));
478
479 if (portletId == null) {
480 portletId = el.attributeValue("portlet-id");
481 }
482
483 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
484 String userUuid = el.attributeValue("archive-user-uuid");
485 String name = el.attributeValue("archive-name");
486
487 long userId = context.getUserId(userUuid);
488
489 PortletItem portletItem =
490 PortletItemLocalServiceUtil.updatePortletItem(
491 userId, groupId, name, portletId,
492 PortletPreferences.class.getName());
493
494 plid = 0;
495 ownerId = portletItem.getPortletItemId();
496 }
497
498 if (defaultUser) {
499 ownerId = defaultUserId;
500 }
501
502 PortletPreferences prefs =
503 PortletPreferencesUtil.fetchByO_O_P_P(
504 ownerId, ownerType, plid, portletId);
505
506 if (prefs != null) {
507 PortletPreferencesLocalServiceUtil.deletePortletPreferences(
508 ownerId, ownerType, plid, portletId);
509 }
510
511 long portletPreferencesId = CounterLocalServiceUtil.increment();
512
513 PortletPreferences portletPreferences =
514 PortletPreferencesUtil.create(portletPreferencesId);
515
516 portletPreferences.setOwnerId(ownerId);
517 portletPreferences.setOwnerType(ownerType);
518 portletPreferences.setPlid(plid);
519 portletPreferences.setPortletId(portletId);
520
521 portletPreferences.setPreferences(preferences);
522
523 PortletPreferencesUtil.update(portletPreferences, true);
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 = DocumentUtil.readDocumentFromXML(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 MBMessage message =
554 (MBMessage)context.fromXML(entry.getValue());
555
556 messages.add(message);
557 }
558
559 context.addComments(className, new Long(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 = DocumentUtil.readDocumentFromXML(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 RatingsEntry rating =
593 (RatingsEntry)context.fromXML(entry.getValue());
594
595 ratings.add(rating);
596 }
597
598 context.addRatingsEntries(className, new Long(classPK), ratings);
599 }
600 }
601 catch (Exception e) {
602 throw new SystemException(e);
603 }
604 }
605
606 protected void readTags(PortletDataContext context, Element parentEl)
607 throws SystemException {
608
609 try {
610 String xml = context.getZipEntryAsString(
611 context.getImportRootPath() + "/tags.xml");
612
613 Document doc = DocumentUtil.readDocumentFromXML(xml);
614
615 Element root = doc.getRootElement();
616
617 List<Element> assets = root.elements("asset");
618
619 for (Element asset : assets) {
620 String className = GetterUtil.getString(
621 asset.attributeValue("class-name"));
622 long classPK = GetterUtil.getLong(
623 asset.attributeValue("class-pk"));
624 String entries = GetterUtil.getString(
625 asset.attributeValue("entries"));
626
627 context.addTagsEntries(
628 className, new Long(classPK),
629 StringUtil.split(entries, ","));
630 }
631 }
632 catch (Exception e) {
633 throw new SystemException(e);
634 }
635 }
636
637 private static Log _log = LogFactory.getLog(PortletImporter.class);
638
639 }