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