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