1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.lar;
16  
17  import com.liferay.portal.LARFileException;
18  import com.liferay.portal.LARTypeException;
19  import com.liferay.portal.LayoutImportException;
20  import com.liferay.portal.PortletIdException;
21  import com.liferay.portal.kernel.exception.PortalException;
22  import com.liferay.portal.kernel.exception.SystemException;
23  import com.liferay.portal.kernel.log.Log;
24  import com.liferay.portal.kernel.log.LogFactoryUtil;
25  import com.liferay.portal.kernel.util.ArrayUtil;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.MapUtil;
28  import com.liferay.portal.kernel.util.ReleaseInfo;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.xml.Document;
31  import com.liferay.portal.kernel.xml.DocumentException;
32  import com.liferay.portal.kernel.xml.Element;
33  import com.liferay.portal.kernel.xml.SAXReaderUtil;
34  import com.liferay.portal.kernel.zip.ZipReader;
35  import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
36  import com.liferay.portal.model.Group;
37  import com.liferay.portal.model.Layout;
38  import com.liferay.portal.model.Portlet;
39  import com.liferay.portal.model.PortletConstants;
40  import com.liferay.portal.model.PortletItem;
41  import com.liferay.portal.model.PortletPreferences;
42  import com.liferay.portal.model.User;
43  import com.liferay.portal.service.GroupLocalServiceUtil;
44  import com.liferay.portal.service.LayoutLocalServiceUtil;
45  import com.liferay.portal.service.PortletItemLocalServiceUtil;
46  import com.liferay.portal.service.PortletLocalServiceUtil;
47  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
48  import com.liferay.portal.service.UserLocalServiceUtil;
49  import com.liferay.portal.service.persistence.PortletPreferencesUtil;
50  import com.liferay.portal.service.persistence.UserUtil;
51  import com.liferay.portal.util.PortletKeys;
52  import com.liferay.portlet.PortletPreferencesFactoryUtil;
53  import com.liferay.portlet.PortletPreferencesImpl;
54  import com.liferay.portlet.PortletPreferencesSerializer;
55  import com.liferay.portlet.asset.NoSuchCategoryException;
56  import com.liferay.portlet.asset.model.AssetCategory;
57  import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
58  import com.liferay.portlet.messageboards.model.MBMessage;
59  import com.liferay.portlet.ratings.model.RatingsEntry;
60  import com.liferay.portlet.social.util.SocialActivityThreadLocal;
61  
62  import java.io.File;
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  /**
72   * <a href="PortletImporter.java.html"><b><i>View Source</i></b></a>
73   *
74   * @author Brian Wing Shun Chan
75   * @author Joel Kozikowski
76   * @author Charles May
77   * @author Raymond Augé
78   * @author Jorge Ferrer
79   * @author Bruno Farache
80   */
81  public class PortletImporter {
82  
83      public void importPortletInfo(
84              long userId, long plid, long groupId, String portletId,
85              Map<String, String[]> parameterMap, File file)
86          throws PortalException, SystemException {
87  
88          boolean deletePortletData = MapUtil.getBoolean(
89              parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
90          boolean importPortletData = MapUtil.getBoolean(
91              parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
92          boolean importPortletArchivedSetups = MapUtil.getBoolean(
93              parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
94          boolean importPortletSetup = MapUtil.getBoolean(
95              parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
96          boolean importUserPreferences = MapUtil.getBoolean(
97              parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
98          String userIdStrategy = MapUtil.getString(
99              parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
100 
101         StopWatch stopWatch = null;
102 
103         if (_log.isInfoEnabled()) {
104             stopWatch = new StopWatch();
105 
106             stopWatch.start();
107         }
108 
109         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
110 
111         long companyId = layout.getCompanyId();
112 
113         User user = UserUtil.findByPrimaryKey(userId);
114 
115         UserIdStrategy strategy = getUserIdStrategy(user, userIdStrategy);
116 
117         ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
118 
119         PortletDataContext context = new PortletDataContextImpl(
120             companyId, groupId, parameterMap, new HashSet<String>(),
121             strategy, zipReader);
122 
123         context.setPlid(plid);
124         context.setPrivateLayout(layout.isPrivateLayout());
125 
126         // Zip
127 
128         Element root = null;
129 
130         // Manifest
131 
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         // Build compatibility
145 
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         // Type compatibility
160 
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         // Portlet compatibility
169 
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         // Import GroupId
179 
180         long sourceGroupId = GetterUtil.getLong(
181             header.attributeValue("group-id"));
182 
183         context.setSourceGroupId(sourceGroupId);
184 
185         // Read categories, comments, ratings, and tags to make them available
186         // to the data handlers through the context
187 
188         readCategories(context, root);
189         readComments(context, root);
190         readRatings(context, root);
191         readTags(context, root);
192 
193         // Delete portlet data
194 
195         if (_log.isDebugEnabled()) {
196             _log.debug("Deleting portlet data");
197         }
198 
199         if (deletePortletData) {
200             deletePortletData(context, portletId, plid);
201         }
202 
203         Element portletRefEl = root.element("portlet");
204         Element portletEl = null;
205 
206         try {
207             Document portletDoc = SAXReaderUtil.read(
208                 context.getZipEntryAsString(
209                     portletRefEl.attributeValue("path")));
210 
211             portletEl = portletDoc.getRootElement();
212         }
213         catch (DocumentException de) {
214             throw new SystemException(de);
215         }
216 
217         // Portlet preferences
218 
219         importPortletPreferences(
220             context, layout.getCompanyId(), groupId, layout, portletId,
221             portletEl, importPortletSetup, importPortletArchivedSetups,
222             importUserPreferences, true);
223 
224         // Portlet data
225 
226         if (_log.isDebugEnabled()) {
227             _log.debug("Importing portlet data");
228         }
229 
230         if (importPortletData) {
231             Element portletDataRefEl = portletEl.element("portlet-data");
232 
233             if (portletDataRefEl != null) {
234                 importPortletData(context, portletId, plid, portletDataRefEl);
235             }
236             else {
237                 if (_log.isWarnEnabled()) {
238                     _log.warn(
239                         "Could not import portlet data because it cannot be " +
240                             "found in the input");
241                 }
242             }
243         }
244 
245         if (_log.isInfoEnabled()) {
246             _log.info(
247                 "Importing portlet data takes " + stopWatch.getTime() + " ms");
248         }
249 
250         zipReader.close();
251     }
252 
253     protected void deletePortletData(
254             PortletDataContext context, String portletId, long plid)
255         throws SystemException {
256 
257         long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
258         int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
259 
260         PortletPreferences portletPreferences =
261             PortletPreferencesUtil.fetchByO_O_P_P(
262                 ownerId, ownerType, plid, portletId);
263 
264         if (portletPreferences == null) {
265             portletPreferences =
266                 new com.liferay.portal.model.impl.PortletPreferencesImpl();
267         }
268 
269         String xml = deletePortletData(
270             context, portletId, portletPreferences);
271 
272         if (xml != null) {
273             PortletPreferencesLocalServiceUtil.updatePreferences(
274                 ownerId, ownerType, plid, portletId, xml);
275         }
276     }
277 
278     protected String deletePortletData(
279             PortletDataContext context, String portletId,
280             PortletPreferences portletPreferences)
281         throws SystemException {
282 
283         Portlet portlet = PortletLocalServiceUtil.getPortletById(
284             context.getCompanyId(), portletId);
285 
286         if (portlet == null) {
287             if (_log.isDebugEnabled()) {
288                 _log.debug(
289                     "Do not delete portlet data for " + portletId +
290                         " because the portlet does not exist");
291             }
292 
293             return null;
294         }
295 
296         PortletDataHandler portletDataHandler =
297             portlet.getPortletDataHandlerInstance();
298 
299         if (portletDataHandler == null) {
300             if (_log.isDebugEnabled()) {
301                 _log.debug(
302                     "Do not delete portlet data for " + portletId +
303                         " because the portlet does not have a " +
304                             "PortletDataHandler");
305             }
306 
307             return null;
308         }
309 
310         if (_log.isDebugEnabled()) {
311             _log.debug("Deleting data for " + portletId);
312         }
313 
314         PortletPreferencesImpl preferencesImpl =
315             (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
316                 portletPreferences.getPreferences());
317 
318         try {
319             preferencesImpl =
320                 (PortletPreferencesImpl)portletDataHandler.deleteData(
321                     context, portletId, preferencesImpl);
322         }
323         catch (Exception e) {
324             throw new SystemException(e);
325         }
326         finally {
327             context.setGroupId(context.getScopeGroupId());
328         }
329 
330         if (preferencesImpl == null) {
331             return null;
332         }
333 
334         return PortletPreferencesSerializer.toXML(preferencesImpl);
335     }
336 
337     protected UserIdStrategy getUserIdStrategy(
338         User user, String userIdStrategy) {
339 
340         if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
341             return new AlwaysCurrentUserIdStrategy(user);
342         }
343 
344         return new CurrentUserIdStrategy(user);
345     }
346 
347     protected void importPortletData(
348             PortletDataContext context, String portletId, long plid,
349             Element portletDataRefEl)
350         throws SystemException {
351 
352         long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
353         int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
354 
355         PortletPreferences portletPreferences =
356             PortletPreferencesUtil.fetchByO_O_P_P(
357                 ownerId, ownerType, plid, portletId);
358 
359         if (portletPreferences == null) {
360             portletPreferences =
361                 new com.liferay.portal.model.impl.PortletPreferencesImpl();
362         }
363 
364         String xml = importPortletData(
365             context, portletId, portletPreferences, portletDataRefEl);
366 
367         if (xml != null) {
368             PortletPreferencesLocalServiceUtil.updatePreferences(
369                 ownerId, ownerType, plid, portletId, xml);
370         }
371     }
372 
373     protected String importPortletData(
374             PortletDataContext context, String portletId,
375             PortletPreferences portletPreferences, Element portletDataRefEl)
376         throws SystemException {
377 
378         Portlet portlet = PortletLocalServiceUtil.getPortletById(
379             context.getCompanyId(), portletId);
380 
381         if (portlet == null) {
382             if (_log.isDebugEnabled()) {
383                 _log.debug(
384                     "Do not import portlet data for " + portletId +
385                         " because the portlet does not exist");
386             }
387 
388             return null;
389         }
390 
391         PortletDataHandler portletDataHandler =
392             portlet.getPortletDataHandlerInstance();
393 
394         if (portletDataHandler == null) {
395             if (_log.isDebugEnabled()) {
396                 _log.debug(
397                     "Do not import portlet data for " + portletId +
398                         " because the portlet does not have a " +
399                             "PortletDataHandler");
400             }
401 
402             return null;
403         }
404 
405         if (_log.isDebugEnabled()) {
406             _log.debug("Importing data for " + portletId);
407         }
408 
409         // Layout scope
410 
411         long groupId = context.getGroupId();
412 
413         long scopeLayoutId = context.getScopeLayoutId();
414 
415         if (scopeLayoutId == 0) {
416             scopeLayoutId = GetterUtil.getLong(
417                 portletDataRefEl.getParent().attributeValue("scope-layout-id"));
418         }
419 
420         if (scopeLayoutId > 0) {
421             try {
422                 Layout scopeLayout = LayoutLocalServiceUtil.getLayout(
423                     context.getGroupId(), context.isPrivateLayout(),
424                     scopeLayoutId);
425 
426                 Group scopeGroup = null;
427 
428                 if (scopeLayout.hasScopeGroup()) {
429                     scopeGroup = scopeLayout.getScopeGroup();
430                 }
431                 else {
432                     String name = String.valueOf(scopeLayout.getPlid());
433 
434                     scopeGroup = GroupLocalServiceUtil.addGroup(
435                         context.getUserId(null), Layout.class.getName(),
436                         scopeLayout.getPlid(), name, null, 0, null, true, null);
437                 }
438 
439                 context.setGroupId(scopeGroup.getGroupId());
440             }
441             catch (PortalException pe) {
442             }
443         }
444 
445         PortletPreferencesImpl preferencesImpl = null;
446 
447         if (portletPreferences != null) {
448             preferencesImpl = (PortletPreferencesImpl)
449                 PortletPreferencesSerializer.fromDefaultXML(
450                     portletPreferences.getPreferences());
451         }
452 
453         String portletData = context.getZipEntryAsString(
454             portletDataRefEl.attributeValue("path"));
455 
456         try {
457             SocialActivityThreadLocal.setEnabled(false);
458 
459             preferencesImpl =
460                 (PortletPreferencesImpl)portletDataHandler.importData(
461                     context, portletId, preferencesImpl, portletData);
462         }
463         catch (Exception e) {
464             throw new SystemException(e);
465         }
466         finally {
467             context.setGroupId(groupId);
468 
469             SocialActivityThreadLocal.setEnabled(true);
470         }
471 
472         if (preferencesImpl == null) {
473             return null;
474         }
475 
476         return PortletPreferencesSerializer.toXML(preferencesImpl);
477     }
478 
479     protected void importPortletPreferences(
480             PortletDataContext context, long companyId, long groupId,
481             Layout layout, String portletId, Element parentEl,
482             boolean importPortletSetup, boolean importPortletArchivedSetups,
483             boolean importUserPreferences, boolean preserveScopeLayoutId)
484         throws PortalException, SystemException {
485 
486         long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
487         long plid = 0;
488         long scopeLayoutId = 0;
489 
490         if (layout != null) {
491             plid = layout.getPlid();
492 
493             if (preserveScopeLayoutId && (portletId != null)) {
494                 javax.portlet.PortletPreferences jxPreferences =
495                     PortletPreferencesFactoryUtil.getLayoutPortletSetup(
496                         layout, portletId);
497 
498                 scopeLayoutId = GetterUtil.getLong(
499                     jxPreferences.getValue("lfr-scope-layout-id", null));
500 
501                 context.setScopeLayoutId(scopeLayoutId);
502             }
503         }
504 
505         List<Element> preferencesEls = parentEl.elements("portlet-preferences");
506 
507         for (Element preferencesEl : preferencesEls) {
508             String path = preferencesEl.attributeValue("path");
509 
510             if (context.isPathNotProcessed(path)) {
511                 Element el = null;
512                 String xml = null;
513 
514                 try {
515                     xml = context.getZipEntryAsString(path);
516 
517                     Document preferencesDoc = SAXReaderUtil.read(xml);
518 
519                     el = preferencesDoc.getRootElement();
520                 }
521                 catch (DocumentException de) {
522                     throw new SystemException(de);
523                 }
524 
525                 long ownerId = GetterUtil.getLong(
526                     el.attributeValue("owner-id"));
527                 int ownerType = GetterUtil.getInteger(
528                     el.attributeValue("owner-type"));
529 
530                 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
531                     continue;
532                 }
533 
534                 if (((ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
535                      (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) &&
536                     !importPortletSetup) {
537 
538                     continue;
539                 }
540 
541                 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) &&
542                     !importPortletArchivedSetups) {
543 
544                     continue;
545                 }
546 
547                 if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
548                     (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
549                     !importUserPreferences) {
550 
551                     continue;
552                 }
553 
554                 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
555                     plid = PortletKeys.PREFS_PLID_SHARED;
556                     ownerId = context.getGroupId();
557                 }
558 
559                 boolean defaultUser = GetterUtil.getBoolean(
560                     el.attributeValue("default-user"));
561 
562                 if (portletId == null) {
563                     portletId = el.attributeValue("portlet-id");
564                 }
565 
566                 if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
567                     portletId = PortletConstants.getRootPortletId(portletId);
568 
569                     String userUuid = el.attributeValue("archive-user-uuid");
570                     String name = el.attributeValue("archive-name");
571 
572                     long userId = context.getUserId(userUuid);
573 
574                     PortletItem portletItem =
575                         PortletItemLocalServiceUtil.updatePortletItem(
576                             userId, groupId, name, portletId,
577                             PortletPreferences.class.getName());
578 
579                     plid = 0;
580                     ownerId = portletItem.getPortletItemId();
581                 }
582 
583                 if (defaultUser) {
584                     ownerId = defaultUserId;
585                 }
586 
587                 PortletPreferencesLocalServiceUtil.updatePreferences(
588                     ownerId, ownerType, plid, portletId, xml);
589             }
590         }
591 
592         if (preserveScopeLayoutId && (layout != null)) {
593             javax.portlet.PortletPreferences jxPreferences =
594                 PortletPreferencesFactoryUtil.getLayoutPortletSetup(
595                     layout, portletId);
596 
597             try {
598                 jxPreferences.setValue(
599                     "lfr-scope-layout-id", String.valueOf(scopeLayoutId));
600 
601                 jxPreferences.store();
602             }
603             catch (Exception e) {
604                 throw new PortalException(e);
605             }
606             finally {
607                 context.setScopeLayoutId(scopeLayoutId);
608             }
609         }
610     }
611 
612     protected void readComments(PortletDataContext context, Element parentEl)
613         throws SystemException {
614 
615         try {
616             String xml = context.getZipEntryAsString(
617                 context.getSourceRootPath() + "/comments.xml");
618 
619             if (xml == null) {
620                 return;
621             }
622 
623             Document doc = SAXReaderUtil.read(xml);
624 
625             Element root = doc.getRootElement();
626 
627             List<Element> assets = root.elements("asset");
628 
629             for (Element asset : assets) {
630                 String path = asset.attributeValue("path");
631                 String className = asset.attributeValue("class-name");
632                 long classPK = GetterUtil.getLong(
633                     asset.attributeValue("class-pk"));
634 
635                 List<String> zipFolderEntries = context.getZipFolderEntries(
636                     path);
637 
638                 List<MBMessage> messages = new ArrayList<MBMessage>();
639 
640                 for (String zipFolderEntry : zipFolderEntries) {
641                     MBMessage message = (MBMessage)context.getZipEntryAsObject(
642                         zipFolderEntry);
643 
644                     if (message != null) {
645                         messages.add(message);
646                     }
647                 }
648 
649                 context.addComments(className, classPK, messages);
650             }
651         }
652         catch (Exception e) {
653             throw new SystemException(e);
654         }
655     }
656 
657     protected void readRatings(PortletDataContext context, Element parentEl)
658         throws SystemException {
659 
660         try {
661             String xml = context.getZipEntryAsString(
662                 context.getSourceRootPath() + "/ratings.xml");
663 
664             if (xml == null) {
665                 return;
666             }
667 
668             Document doc = SAXReaderUtil.read(xml);
669 
670             Element root = doc.getRootElement();
671 
672             List<Element> assets = root.elements("asset");
673 
674             for (Element asset : assets) {
675                 String path = asset.attributeValue("path");
676                 String className = asset.attributeValue("class-name");
677                 long classPK = GetterUtil.getLong(
678                     asset.attributeValue("class-pk"));
679 
680                 List<String> zipFolderEntries = context.getZipFolderEntries(
681                     path);
682 
683                 List<RatingsEntry> ratingsEntries =
684                     new ArrayList<RatingsEntry>();
685 
686                 for (String zipFolderEntry : zipFolderEntries) {
687                     RatingsEntry ratingsEntry =
688                         (RatingsEntry)context.getZipEntryAsObject(
689                             zipFolderEntry);
690 
691                     if (ratingsEntry != null) {
692                         ratingsEntries.add(ratingsEntry);
693                     }
694                 }
695 
696                 context.addRatingsEntries(
697                     className, new Long(classPK), ratingsEntries);
698             }
699         }
700         catch (Exception e) {
701             throw new SystemException(e);
702         }
703     }
704 
705     protected void readCategories(PortletDataContext context, Element parentEl)
706         throws SystemException {
707 
708         try {
709             String xml = context.getZipEntryAsString(
710                 context.getSourceRootPath() + "/categories.xml");
711 
712             if (xml == null) {
713                 return;
714             }
715 
716             Document doc = SAXReaderUtil.read(xml);
717 
718             Element root = doc.getRootElement();
719 
720             List<Element> assets = root.elements("asset");
721 
722             for (Element asset : assets) {
723                 String className = GetterUtil.getString(
724                     asset.attributeValue("class-name"));
725                 long classPK = GetterUtil.getLong(
726                     asset.attributeValue("class-pk"));
727                 String[] assetCategoryUuids = StringUtil.split(
728                     GetterUtil.getString(
729                         asset.attributeValue("category-uuids")));
730 
731                 long[] assetCategoryIds = new long[0];
732 
733                 for (String assetCategoryUuid : assetCategoryUuids) {
734                     try {
735                         AssetCategory assetCategory =
736                             AssetCategoryUtil.findByUUID_G(
737                                 assetCategoryUuid, context.getScopeGroupId());
738 
739                         assetCategoryIds = ArrayUtil.append(
740                             assetCategoryIds, assetCategory.getCategoryId());
741                     }
742                     catch (NoSuchCategoryException nsce) {
743                     }
744                 }
745 
746                 context.addAssetCategories(
747                     className, new Long(classPK), assetCategoryIds);
748             }
749         }
750         catch (Exception e) {
751             throw new SystemException(e);
752         }
753     }
754 
755     protected void readTags(PortletDataContext context, Element parentEl)
756         throws SystemException {
757 
758         try {
759             String xml = context.getZipEntryAsString(
760                 context.getSourceRootPath() + "/tags.xml");
761 
762             if (xml == null) {
763                 return;
764             }
765 
766             Document doc = SAXReaderUtil.read(xml);
767 
768             Element root = doc.getRootElement();
769 
770             List<Element> assets = root.elements("asset");
771 
772             for (Element asset : assets) {
773                 String className = GetterUtil.getString(
774                     asset.attributeValue("class-name"));
775                 long classPK = GetterUtil.getLong(
776                     asset.attributeValue("class-pk"));
777                 String assetTagNames = GetterUtil.getString(
778                     asset.attributeValue("tags"));
779 
780                 context.addAssetTags(
781                     className, new Long(classPK),
782                     StringUtil.split(assetTagNames));
783             }
784         }
785         catch (Exception e) {
786             throw new SystemException(e);
787         }
788     }
789 
790     private static Log _log = LogFactoryUtil.getLog(PortletImporter.class);
791 
792 }