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