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