@Override
  public PortletPreferences doImportData(
      PortletDataContext context, String portletId, PortletPreferences preferences, String data)
      throws PortletDataException {

    long communityId = context.getScopeGroupId();

    LOGGER.debug(
        "Importing CRUD portlet data for portletId {}, communityId {}", portletId, communityId);

    checkCompatibility(preferences);

    try {
      ZipReader zipReader = context.getZipReader();
      byte[] portletConfigData =
          zipReader.getEntryAsByteArray(portletId + "/portletConfiguration.xml");

      if (portletConfigData != null) {
        configurationService.storeConfigurationFile(
            data, portletConfigData, portletId, communityId, "import");

        Map<String, Long> newRoleIds = createResourceRoles(portletId, communityId, preferences);

        importPermissions(context, preferences, newRoleIds);
      }

      return null;

    } catch (RuntimeException e) {
      throw new PortletDataException("Error importing portlet " + portletId + "/" + communityId, e);
    }
  }
  @Test
  public void testValidateMissingReferences() throws Exception {
    String xml = replaceParameters(getContent("missing_references.txt"), _fileEntry);

    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();

    zipWriter.addEntry("/manifest.xml", xml);

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(zipWriter.getFile());

    _portletDataContextImport.setZipReader(zipReader);

    MissingReferences missingReferences =
        ExportImportHelperUtil.validateMissingReferences(_portletDataContextImport);

    Map<String, MissingReference> dependencyMissingReferences =
        missingReferences.getDependencyMissingReferences();

    Map<String, MissingReference> weakMissingReferences =
        missingReferences.getWeakMissingReferences();

    Assert.assertEquals(2, dependencyMissingReferences.size());
    Assert.assertEquals(1, weakMissingReferences.size());

    FileUtil.delete(zipWriter.getFile());

    zipReader.close();
  }
  @Override
  public void importDataDeletions(ExportImportConfiguration exportImportConfiguration, File file)
      throws Exception {

    ZipReader zipReader = null;

    try {

      // LAR validation

      ExportImportThreadLocal.setPortletDataDeletionImportInProcess(true);

      Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap();

      Map<String, String[]> parameterMap = (Map<String, String[]>) settingsMap.get("parameterMap");
      String portletId = MapUtil.getString(settingsMap, "portletId");
      long targetPlid = MapUtil.getLong(settingsMap, "targetPlid");
      long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId");

      Layout layout = _layoutLocalService.getLayout(targetPlid);

      zipReader = ZipReaderFactoryUtil.getZipReader(file);

      validateFile(layout.getCompanyId(), targetGroupId, portletId, zipReader);

      PortletDataContext portletDataContext =
          getPortletDataContext(exportImportConfiguration, file);

      boolean deletePortletData =
          MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);

      // Portlet data deletion

      if (deletePortletData) {
        if (_log.isDebugEnabled()) {
          _log.debug("Deleting portlet data");
        }

        deletePortletData(portletDataContext);
      }

      // Deletion system events

      populateDeletionStagedModelTypes(portletDataContext);

      _deletionSystemEventImporter.importDeletionSystemEvents(portletDataContext);
    } finally {
      ExportImportThreadLocal.setPortletDataDeletionImportInProcess(false);

      if (zipReader != null) {
        zipReader.close();
      }
    }
  }
  @Override
  @Transactional(enabled = false)
  public Map<String, Object> updateFileEntries(File zipFile) throws PortalException {

    Map<String, Object> responseMap = new HashMap<>();

    ZipReader zipReader = null;

    try {
      zipReader = ZipReaderFactoryUtil.getZipReader(zipFile);

      String manifest = zipReader.getEntryAsString("/manifest.json");

      JSONArray jsonArray = JSONFactoryUtil.createJSONArray(manifest);

      for (int i = 0; i < jsonArray.length(); i++) {
        JSONObject jsonObject = jsonArray.getJSONObject(i);

        JSONWebServiceActionParametersMap jsonWebServiceActionParametersMap =
            JSONFactoryUtil.looseDeserialize(
                jsonObject.toString(), JSONWebServiceActionParametersMap.class);

        String zipFileId = MapUtil.getString(jsonWebServiceActionParametersMap, "zipFileId");

        try {
          responseMap.put(
              zipFileId,
              updateFileEntries(zipReader, zipFileId, jsonWebServiceActionParametersMap));
        } catch (Exception e) {
          String message = e.getMessage();

          if (!message.startsWith(StringPool.QUOTE) && !message.endsWith(StringPool.QUOTE)) {

            message = StringUtil.quote(message, StringPool.QUOTE);
          }

          String json = "{\"exception\": " + message + "}";

          responseMap.put(zipFileId, json);
        }
      }
    } finally {
      if (zipReader != null) {
        zipReader.close();
      }
    }

    return responseMap;
  }
  protected Layout importLayoutFromLAR(StagedModel stagedModel)
      throws DocumentException, IOException {

    LayoutSetPrototypeStagedModelDataHandler layoutSetPrototypeStagedModelDataHandler =
        new LayoutSetPrototypeStagedModelDataHandler();

    String fileName =
        layoutSetPrototypeStagedModelDataHandler.getLayoutSetPrototypeLARFileName(
            (LayoutSetPrototype) stagedModel);

    String modelPath = ExportImportPathUtil.getModelPath(stagedModel, fileName);

    InputStream inputStream = portletDataContext.getZipEntryAsInputStream(modelPath);

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(inputStream);

    Document document = UnsecureSAXReaderUtil.read(zipReader.getEntryAsString("manifest.xml"));

    Element rootElement = document.getRootElement();

    Element layoutElement = rootElement.element("Layout");

    List<Element> elements = layoutElement.elements();

    List<Layout> importedLayouts = new ArrayList<>(elements.size());

    for (Element element : elements) {
      String layoutPrototypeUuid = element.attributeValue("layout-prototype-uuid");

      if (Validator.isNotNull(layoutPrototypeUuid)) {
        String path = element.attributeValue("path");

        Layout layout = (Layout) portletDataContext.fromXML(zipReader.getEntryAsString(path));

        importedLayouts.add(layout);
      }
    }

    Assert.assertEquals(1, importedLayouts.size());

    try {
      return importedLayouts.get(0);
    } finally {
      zipReader.close();

      StreamUtil.cleanUp(inputStream);
    }
  }
  protected Map<String, String> getMetadata(ZipReader zipReader) throws KBArticleImportException {

    InputStream inputStream = null;

    try {
      inputStream = zipReader.getEntryAsInputStream(".METADATA");

      if (inputStream == null) {
        return Collections.emptyMap();
      }

      Properties properties = new Properties();

      properties.load(inputStream);

      Map<String, String> metadata = new HashMap<String, String>(properties.size());

      for (Object key : properties.keySet()) {
        Object value = properties.get(key);

        if (value != null) {
          metadata.put(key.toString(), value.toString());
        }
      }

      return metadata;
    } catch (IOException ioe) {
      throw new KBArticleImportException(ioe);
    } finally {
      StreamUtil.cleanUp(inputStream);
    }
  }
  protected Map<String, List<String>> getFolderNameFileEntryNamesMap(ZipReader zipReader) {

    Map<String, List<String>> folderNameFileEntryNamesMap = new TreeMap<String, List<String>>();

    for (String zipEntry : zipReader.getEntries()) {
      String extension = FileUtil.getExtension(zipEntry);

      if (!ArrayUtil.contains(
              PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_EXTENSIONS,
              StringPool.PERIOD.concat(extension))
          || zipEntry.equals(PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_HOME)) {

        continue;
      }

      String folderName = zipEntry.substring(0, zipEntry.lastIndexOf(StringPool.SLASH));

      List<String> fileEntryNames = folderNameFileEntryNamesMap.get(folderName);

      if (fileEntryNames == null) {
        fileEntryNames = new ArrayList<String>();
      }

      fileEntryNames.add(zipEntry);

      folderNameFileEntryNamesMap.put(folderName, fileEntryNames);
    }

    return folderNameFileEntryNamesMap;
  }
  protected void processKBArticleFiles(
      long userId, long groupId, ZipReader zipReader, ServiceContext serviceContext)
      throws KBArticleImportException {

    long parentResourcePrimKey = KBArticleConstants.DEFAULT_PARENT_RESOURCE_PRIM_KEY;

    String markdown = zipReader.getEntryAsString(PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_HOME);

    if (Validator.isNotNull(markdown)) {
      KBArticle parentKBArticle =
          addKBArticleMarkdown(
              userId,
              groupId,
              KBArticleConstants.DEFAULT_PARENT_RESOURCE_PRIM_KEY,
              markdown,
              PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_HOME,
              zipReader,
              serviceContext);

      parentResourcePrimKey = parentKBArticle.getResourcePrimKey();
    }

    processSectionKBArticleFiles(
        userId,
        groupId,
        parentResourcePrimKey,
        zipReader,
        getFolderNameFileEntryNamesMap(zipReader),
        serviceContext);
  }
  @Override
  public MissingReferences validateFile(
      ExportImportConfiguration exportImportConfiguration, File file) throws Exception {

    ZipReader zipReader = null;

    try {
      ExportImportThreadLocal.setPortletValidationInProcess(true);

      Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap();

      String portletId = MapUtil.getString(settingsMap, "portletId");
      long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId");
      long targetPlid = MapUtil.getLong(settingsMap, "targetPlid");

      Layout layout = _layoutLocalService.getLayout(targetPlid);

      zipReader = ZipReaderFactoryUtil.getZipReader(file);

      validateFile(layout.getCompanyId(), targetGroupId, portletId, zipReader);

      PortletDataContext portletDataContext =
          getPortletDataContext(exportImportConfiguration, file);

      MissingReferences missingReferences =
          ExportImportHelperUtil.validateMissingReferences(portletDataContext);

      Map<String, MissingReference> dependencyMissingReferences =
          missingReferences.getDependencyMissingReferences();

      if (!dependencyMissingReferences.isEmpty()) {
        throw new MissingReferenceException(missingReferences);
      }

      return missingReferences;
    } finally {
      ExportImportThreadLocal.setPortletValidationInProcess(false);

      if (zipReader != null) {
        zipReader.close();
      }
    }
  }
  protected void validateFile(long companyId, long groupId, String portletId, ZipReader zipReader)
      throws Exception {

    // XML

    String xml = zipReader.getEntryAsString("/manifest.xml");

    if (xml == null) {
      throw new LARFileException("manifest.xml not found in the LAR");
    }

    Element rootElement = null;

    try {
      Document document = SAXReaderUtil.read(xml);

      rootElement = document.getRootElement();
    } catch (Exception e) {
      throw new LARFileException(e);
    }

    // Build compatibility

    int buildNumber = ReleaseInfo.getBuildNumber();

    Element headerElement = rootElement.element("header");

    int importBuildNumber = GetterUtil.getInteger(headerElement.attributeValue("build-number"));

    if (buildNumber != importBuildNumber) {
      throw new LayoutImportException(
          "LAR build number "
              + importBuildNumber
              + " does not match "
              + "portal build number "
              + buildNumber);
    }

    // Type

    String larType = headerElement.attributeValue("type");

    if (!larType.equals("portlet")) {
      throw new LARTypeException(larType);
    }

    // Portlet compatibility

    String rootPortletId = headerElement.attributeValue("root-portlet-id");

    if (!PortletConstants.getRootPortletId(portletId).equals(rootPortletId)) {

      throw new PortletIdException("Invalid portlet id " + rootPortletId);
    }

    // Available locales

    Portlet portlet = _portletLocalService.getPortletById(companyId, portletId);

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    if (portletDataHandler.isDataLocalized()) {
      List<Locale> sourceAvailableLocales =
          Arrays.asList(
              LocaleUtil.fromLanguageIds(
                  StringUtil.split(headerElement.attributeValue("available-locales"))));

      for (Locale sourceAvailableLocale : sourceAvailableLocales) {
        if (!LanguageUtil.isAvailableLocale(
            PortalUtil.getSiteGroupId(groupId), sourceAvailableLocale)) {

          LocaleException le =
              new LocaleException(
                  LocaleException.TYPE_EXPORT_IMPORT,
                  "Locale "
                      + sourceAvailableLocale
                      + " is not "
                      + "available in company "
                      + companyId);

          le.setSourceAvailableLocales(sourceAvailableLocales);
          le.setTargetAvailableLocales(
              LanguageUtil.getAvailableLocales(PortalUtil.getSiteGroupId(groupId)));

          throw le;
        }
      }
    }
  }
  protected void processSectionKBArticleFiles(
      long userId,
      long groupId,
      long parentResourcePrimaryKey,
      ZipReader zipReader,
      Map<String, List<String>> folderNameFileEntryNamesMap,
      Map<String, String> metadata,
      ServiceContext serviceContext)
      throws KBArticleImportException {

    Set<String> folderNames = folderNameFileEntryNamesMap.keySet();

    for (String folderName : folderNames) {
      List<String> fileEntryNames = folderNameFileEntryNamesMap.get(folderName);

      String sectionIntroFileEntryName = null;

      List<String> sectionFileEntryNames = new ArrayList<String>();

      for (String fileEntryName : fileEntryNames) {
        if (fileEntryName.endsWith(PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_INTRO)) {

          sectionIntroFileEntryName = fileEntryName;
        } else {
          sectionFileEntryNames.add(fileEntryName);
        }
      }

      if (Validator.isNull(sectionIntroFileEntryName) && !sectionFileEntryNames.isEmpty()) {

        StringBundler sb = new StringBundler(4);

        sb.append("No file entry ending in ");
        sb.append(PortletPropsValues.MARKDOWN_IMPORTER_ARTICLE_INTRO);
        sb.append(" accompanies file entry ");
        sb.append(sectionFileEntryNames.get(0));

        throw new KBArticleImportException(sb.toString());
      }

      KBArticle sectionIntroKBArticle =
          addKBArticleMarkdown(
              userId,
              groupId,
              parentResourcePrimaryKey,
              zipReader.getEntryAsString(sectionIntroFileEntryName),
              sectionIntroFileEntryName,
              zipReader,
              metadata,
              serviceContext);

      for (String sectionFileEntryName : sectionFileEntryNames) {
        String sectionMarkdown = zipReader.getEntryAsString(sectionFileEntryName);

        if (Validator.isNull(sectionMarkdown)) {
          if (_log.isWarnEnabled()) {
            _log.warn("Missing Markdown in file entry " + sectionFileEntryName);
          }
        }

        addKBArticleMarkdown(
            userId,
            groupId,
            sectionIntroKBArticle.getResourcePrimKey(),
            sectionMarkdown,
            sectionFileEntryName,
            zipReader,
            metadata,
            serviceContext);
      }
    }
  }
  protected void doImportLayouts(
      long userId,
      long groupId,
      boolean privateLayout,
      Map<String, String[]> parameterMap,
      File file)
      throws Exception {

    boolean deleteMissingLayouts =
        MapUtil.getBoolean(
            parameterMap,
            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
            Boolean.TRUE.booleanValue());
    boolean deletePortletData =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
    boolean importCategories = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.CATEGORIES);
    boolean importPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);
    boolean importPublicLayoutPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PUBLIC_LAYOUT_PERMISSIONS);
    boolean importUserPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
    boolean importPortletData =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
    boolean importPortletSetup =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
    boolean importPortletArchivedSetups =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
    boolean importPortletUserPreferences =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
    boolean importTheme = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.THEME);
    boolean importThemeSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.THEME_REFERENCE);
    boolean importLogo = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LOGO);
    boolean importLayoutSetSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);

    boolean layoutSetPrototypeLinkEnabled =
        MapUtil.getBoolean(
            parameterMap, PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED, true);

    Group group = GroupLocalServiceUtil.getGroup(groupId);

    if (group.isLayoutSetPrototype()) {
      layoutSetPrototypeLinkEnabled = false;
    }

    boolean publishToRemote =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PUBLISH_TO_REMOTE);
    String layoutsImportMode =
        MapUtil.getString(
            parameterMap,
            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
    String portletsMergeMode =
        MapUtil.getString(
            parameterMap,
            PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
            PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
    String userIdStrategy =
        MapUtil.getString(parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);

    if (_log.isDebugEnabled()) {
      _log.debug("Delete portlet data " + deletePortletData);
      _log.debug("Import categories " + importCategories);
      _log.debug("Import permissions " + importPermissions);
      _log.debug("Import user permissions " + importUserPermissions);
      _log.debug("Import portlet data " + importPortletData);
      _log.debug("Import portlet setup " + importPortletSetup);
      _log.debug("Import portlet archived setups " + importPortletArchivedSetups);
      _log.debug("Import portlet user preferences " + importPortletUserPreferences);
      _log.debug("Import theme " + importTheme);
    }

    StopWatch stopWatch = null;

    if (_log.isInfoEnabled()) {
      stopWatch = new StopWatch();

      stopWatch.start();
    }

    LayoutCache layoutCache = new LayoutCache();

    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(groupId, privateLayout);

    long companyId = layoutSet.getCompanyId();

    User user = UserUtil.findByPrimaryKey(userId);

    UserIdStrategy strategy = _portletImporter.getUserIdStrategy(user, userIdStrategy);

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);

    PortletDataContext portletDataContext =
        new PortletDataContextImpl(
            companyId, groupId, parameterMap, new HashSet<String>(), strategy, zipReader);

    portletDataContext.setPortetDataContextListener(
        new PortletDataContextListenerImpl(portletDataContext));

    portletDataContext.setPrivateLayout(privateLayout);

    // Zip

    Element rootElement = null;
    InputStream themeZip = null;

    // Manifest

    String xml = portletDataContext.getZipEntryAsString("/manifest.xml");

    if (xml == null) {
      throw new LARFileException("manifest.xml not found in the LAR");
    }

    try {
      Document document = SAXReaderUtil.read(xml);

      rootElement = document.getRootElement();
    } catch (Exception e) {
      throw new LARFileException(e);
    }

    // Build compatibility

    Element headerElement = rootElement.element("header");

    int buildNumber = ReleaseInfo.getBuildNumber();

    int importBuildNumber = GetterUtil.getInteger(headerElement.attributeValue("build-number"));

    if (buildNumber != importBuildNumber) {
      throw new LayoutImportException(
          "LAR build number "
              + importBuildNumber
              + " does not match "
              + "portal build number "
              + buildNumber);
    }

    // Type compatibility

    String larType = headerElement.attributeValue("type");

    if (!larType.equals("layout-set") && !larType.equals("layout-set-prototype")) {

      throw new LARTypeException("Invalid type of LAR file (" + larType + ")");
    }

    // Group id

    long sourceGroupId = GetterUtil.getLong(headerElement.attributeValue("group-id"));

    portletDataContext.setSourceGroupId(sourceGroupId);

    // Layout set prototype

    if (group.isLayoutSetPrototype() && larType.equals("layout-set-prototype")) {

      LayoutSetPrototype layoutSetPrototype =
          LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(group.getClassPK());

      String layoutSetPrototypeUuid =
          GetterUtil.getString(headerElement.attributeValue("type-uuid"));

      LayoutSetPrototype existingLayoutSetPrototype = null;

      if (Validator.isNotNull(layoutSetPrototypeUuid)) {
        try {
          existingLayoutSetPrototype =
              LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototypeByUuid(
                  layoutSetPrototypeUuid);
        } catch (NoSuchLayoutSetPrototypeException nslspe) {
        }
      }

      if (existingLayoutSetPrototype == null) {
        layoutSetPrototype.setUuid(layoutSetPrototypeUuid);

        LayoutSetPrototypeLocalServiceUtil.updateLayoutSetPrototype(layoutSetPrototype);
      }
    }

    Element layoutsElement = rootElement.element("layouts");

    String layoutSetPrototypeUuid = layoutsElement.attributeValue("layout-set-prototype-uuid");

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (Validator.isNotNull(layoutSetPrototypeUuid)) {
      if (layoutSetPrototypeLinkEnabled) {
        if (publishToRemote) {
          importLayoutSetPrototype(
              portletDataContext, user, layoutSetPrototypeUuid, serviceContext);
        }
      }

      layoutSet.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid);
      layoutSet.setLayoutSetPrototypeLinkEnabled(layoutSetPrototypeLinkEnabled);

      LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
    }

    // Look and feel

    if (importTheme) {
      themeZip = portletDataContext.getZipEntryAsInputStream("theme.zip");
    }

    // Look and feel

    String themeId = layoutSet.getThemeId();
    String colorSchemeId = layoutSet.getColorSchemeId();

    if (importThemeSettings) {
      Attribute themeIdAttribute = headerElement.attribute("theme-id");

      if (themeIdAttribute != null) {
        themeId = themeIdAttribute.getValue();
      }

      Attribute colorSchemeIdAttribute = headerElement.attribute("color-scheme-id");

      if (colorSchemeIdAttribute != null) {
        colorSchemeId = colorSchemeIdAttribute.getValue();
      }
    }

    if (importLogo) {
      String logoPath = headerElement.attributeValue("logo-path");

      byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(logoPath);

      if ((iconBytes != null) && (iconBytes.length > 0)) {
        File logo = FileUtil.createTempFile(iconBytes);

        LayoutSetLocalServiceUtil.updateLogo(groupId, privateLayout, true, logo);
      } else {
        LayoutSetLocalServiceUtil.updateLogo(groupId, privateLayout, false, (File) null);
      }
    }

    if (importLayoutSetSettings) {
      String settings = GetterUtil.getString(headerElement.elementText("settings"));

      LayoutSetLocalServiceUtil.updateSettings(groupId, privateLayout, settings);
    }

    String css = GetterUtil.getString(headerElement.elementText("css"));

    if (themeZip != null) {
      String importThemeId = importTheme(layoutSet, themeZip);

      if (importThemeId != null) {
        themeId = importThemeId;
        colorSchemeId = ColorSchemeImpl.getDefaultRegularColorSchemeId();
      }

      if (_log.isDebugEnabled()) {
        _log.debug("Importing theme takes " + stopWatch.getTime() + " ms");
      }
    }

    boolean wapTheme = false;

    LayoutSetLocalServiceUtil.updateLookAndFeel(
        groupId, privateLayout, themeId, colorSchemeId, css, wapTheme);

    // Read asset categories, asset tags, comments, locks, permissions, and
    // ratings entries to make them available to the data handlers through
    // the context

    if (importPermissions) {
      _permissionImporter.readPortletDataPermissions(portletDataContext);
    }

    if (importCategories) {
      _portletImporter.readAssetCategories(portletDataContext);
    }

    _portletImporter.readAssetTags(portletDataContext);
    _portletImporter.readComments(portletDataContext);
    _portletImporter.readExpandoTables(portletDataContext);
    _portletImporter.readLocks(portletDataContext);
    _portletImporter.readRatingsEntries(portletDataContext);

    // Layouts

    List<Layout> previousLayouts = LayoutUtil.findByG_P(groupId, privateLayout);

    // Remove layouts that were deleted from the layout set prototype

    if (Validator.isNotNull(layoutSetPrototypeUuid) && layoutSetPrototypeLinkEnabled) {

      LayoutSetPrototype layoutSetPrototype =
          LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototypeByUuid(layoutSetPrototypeUuid);

      Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();

      for (Layout layout : previousLayouts) {
        String sourcePrototypeLayoutUuid = layout.getSourcePrototypeLayoutUuid();

        if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
          continue;
        }

        Layout sourcePrototypeLayout =
            LayoutUtil.fetchByUUID_G(
                sourcePrototypeLayoutUuid, layoutSetPrototypeGroup.getGroupId());

        if (sourcePrototypeLayout == null) {
          LayoutLocalServiceUtil.deleteLayout(layout, false, serviceContext);
        }
      }
    }

    List<Layout> newLayouts = new ArrayList<Layout>();

    Set<Long> newLayoutIds = new HashSet<Long>();

    Map<Long, Layout> newLayoutsMap =
        (Map<Long, Layout>) portletDataContext.getNewPrimaryKeysMap(Layout.class);

    List<Element> layoutElements = layoutsElement.elements("layout");

    if (_log.isDebugEnabled()) {
      if (layoutElements.size() > 0) {
        _log.debug("Importing layouts");
      }
    }

    for (Element layoutElement : layoutElements) {
      importLayout(
          portletDataContext,
          user,
          layoutCache,
          previousLayouts,
          newLayouts,
          newLayoutsMap,
          newLayoutIds,
          portletsMergeMode,
          themeId,
          colorSchemeId,
          layoutsImportMode,
          privateLayout,
          importPermissions,
          importPublicLayoutPermissions,
          importUserPermissions,
          importThemeSettings,
          rootElement,
          layoutElement);
    }

    Element portletsElement = rootElement.element("portlets");

    List<Element> portletElements = portletsElement.elements("portlet");

    // Delete portlet data

    if (deletePortletData) {
      if (_log.isDebugEnabled()) {
        if (portletElements.size() > 0) {
          _log.debug("Deleting portlet data");
        }
      }

      for (Element portletElement : portletElements) {
        String portletId = portletElement.attributeValue("portlet-id");
        long layoutId = GetterUtil.getLong(portletElement.attributeValue("layout-id"));
        long plid = newLayoutsMap.get(layoutId).getPlid();

        portletDataContext.setPlid(plid);

        _portletImporter.deletePortletData(portletDataContext, portletId, plid);
      }
    }

    // Import portlets

    if (_log.isDebugEnabled()) {
      if (portletElements.size() > 0) {
        _log.debug("Importing portlets");
      }
    }

    for (Element portletElement : portletElements) {
      String portletPath = portletElement.attributeValue("path");
      String portletId = portletElement.attributeValue("portlet-id");
      long layoutId = GetterUtil.getLong(portletElement.attributeValue("layout-id"));
      long plid = newLayoutsMap.get(layoutId).getPlid();
      long oldPlid = GetterUtil.getLong(portletElement.attributeValue("old-plid"));

      Portlet portlet =
          PortletLocalServiceUtil.getPortletById(portletDataContext.getCompanyId(), portletId);

      if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
        continue;
      }

      Layout layout = null;

      try {
        layout = LayoutUtil.findByPrimaryKey(plid);
      } catch (NoSuchLayoutException nsle) {
        continue;
      }

      portletDataContext.setPlid(plid);
      portletDataContext.setOldPlid(oldPlid);

      Document portletDocument =
          SAXReaderUtil.read(portletDataContext.getZipEntryAsString(portletPath));

      portletElement = portletDocument.getRootElement();

      // The order of the import is important. You must always import
      // the portlet preferences first, then the portlet data, then
      // the portlet permissions. The import of the portlet data
      // assumes that portlet preferences already exist.

      _portletImporter.setPortletScope(portletDataContext, portletElement);

      try {

        // Portlet preferences

        _portletImporter.importPortletPreferences(
            portletDataContext,
            layoutSet.getCompanyId(),
            layout.getGroupId(),
            layout,
            null,
            portletElement,
            importPortletSetup,
            importPortletArchivedSetups,
            importPortletUserPreferences,
            false);

        // Portlet data

        Element portletDataElement = portletElement.element("portlet-data");

        if (importPortletData && (portletDataElement != null)) {
          _portletImporter.importPortletData(
              portletDataContext, portletId, plid, portletDataElement);
        }
      } finally {
        _portletImporter.resetPortletScope(portletDataContext, layout.getGroupId());
      }

      // Portlet permissions

      if (importPermissions) {
        _permissionImporter.importPortletPermissions(
            layoutCache,
            companyId,
            groupId,
            userId,
            layout,
            portletElement,
            portletId,
            importUserPermissions);
      }

      // Archived setups

      _portletImporter.importPortletPreferences(
          portletDataContext,
          layoutSet.getCompanyId(),
          groupId,
          null,
          null,
          portletElement,
          importPortletSetup,
          importPortletArchivedSetups,
          importPortletUserPreferences,
          false);
    }

    if (importPermissions) {
      if ((userId > 0)
          && ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5)
              || (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6))) {

        Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);

        indexer.reindex(userId);
      }
    }

    // Asset links

    _portletImporter.readAssetLinks(portletDataContext);

    // Delete missing layouts

    if (deleteMissingLayouts) {
      deleteMissingLayouts(groupId, privateLayout, newLayoutIds, previousLayouts, serviceContext);
    }

    // Page count

    LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);

    if (_log.isInfoEnabled()) {
      _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
    }

    // Site

    GroupLocalServiceUtil.updateSite(groupId, true);

    // Web content layout type

    for (Layout layout : newLayouts) {
      UnicodeProperties typeSettingsProperties = layout.getTypeSettingsProperties();

      String articleId = typeSettingsProperties.getProperty("article-id");

      if (Validator.isNotNull(articleId)) {
        Map<String, String> articleIds =
            (Map<String, String>)
                portletDataContext.getNewPrimaryKeysMap(JournalArticle.class + ".articleId");

        typeSettingsProperties.setProperty(
            "article-id", MapUtil.getString(articleIds, articleId, articleId));

        LayoutUtil.update(layout, false);
      }
    }

    zipReader.close();
  }
  protected String importTheme(LayoutSet layoutSet, InputStream themeZip) throws Exception {

    ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();

    if (themeLoader == null) {
      _log.error("No theme loaders are deployed");

      return null;
    }

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(themeZip);

    String lookAndFeelXML = zipReader.getEntryAsString("liferay-look-and-feel.xml");

    String themeId = String.valueOf(layoutSet.getGroupId());

    if (layoutSet.isPrivateLayout()) {
      themeId += "-private";
    } else {
      themeId += "-public";
    }

    if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
      Date now = new Date();

      themeId += "-" + Time.getShortTimestamp(now);
    }

    String themeName = themeId;

    lookAndFeelXML =
        StringUtil.replace(
            lookAndFeelXML,
            new String[] {"[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"},
            new String[] {String.valueOf(layoutSet.getGroupId()), themeId, themeName});

    FileUtil.deltree(themeLoader.getFileStorage() + StringPool.SLASH + themeId);

    List<String> zipEntries = zipReader.getEntries();

    for (String zipEntry : zipEntries) {
      String key = zipEntry;

      if (key.equals("liferay-look-and-feel.xml")) {
        FileUtil.write(
            themeLoader.getFileStorage() + StringPool.SLASH + themeId + StringPool.SLASH + key,
            lookAndFeelXML.getBytes());
      } else {
        InputStream is = zipReader.getEntryAsInputStream(zipEntry);

        FileUtil.write(
            themeLoader.getFileStorage() + StringPool.SLASH + themeId + StringPool.SLASH + key, is);
      }
    }

    themeLoader.loadThemes();

    ClusterRequest clusterRequest =
        ClusterRequest.createMulticastRequest(_loadThemesMethodHandler, true);

    clusterRequest.setFireAndForget(true);

    ClusterExecutorUtil.execute(clusterRequest);

    themeId += PortletConstants.WAR_SEPARATOR + themeLoader.getServletContextName();

    return PortalUtil.getJsSafePortletId(themeId);
  }
  public void importPortletInfo(
      long userId,
      long plid,
      long groupId,
      String portletId,
      Map<String, String[]> parameterMap,
      File file)
      throws Exception {

    boolean deletePortletData =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
    boolean importPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);
    boolean importUserPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);
    boolean importPortletData =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
    boolean importPortletArchivedSetups =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
    boolean importPortletSetup =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
    boolean importPortletUserPreferences =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
    String userIdStrategyString =
        MapUtil.getString(parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);

    StopWatch stopWatch = null;

    if (_log.isInfoEnabled()) {
      stopWatch = new StopWatch();

      stopWatch.start();
    }

    Layout layout = LayoutLocalServiceUtil.getLayout(plid);

    User user = UserUtil.findByPrimaryKey(userId);

    UserIdStrategy userIdStrategy = getUserIdStrategy(user, userIdStrategyString);

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);

    PortletDataContext portletDataContext =
        new PortletDataContextImpl(
            layout.getCompanyId(),
            groupId,
            parameterMap,
            new HashSet<String>(),
            userIdStrategy,
            zipReader);

    portletDataContext.setPortetDataContextListener(
        new PortletDataContextListenerImpl(portletDataContext));

    portletDataContext.setPlid(plid);
    portletDataContext.setPrivateLayout(layout.isPrivateLayout());

    // Manifest

    String xml = portletDataContext.getZipEntryAsString("/manifest.xml");

    Element rootElement = null;

    try {
      Document document = SAXReaderUtil.read(xml);

      rootElement = document.getRootElement();
    } catch (Exception e) {
      throw new LARFileException("Unable to read /manifest.xml");
    }

    // Build compatibility

    Element headerElement = rootElement.element("header");

    int buildNumber = ReleaseInfo.getBuildNumber();

    int importBuildNumber = GetterUtil.getInteger(headerElement.attributeValue("build-number"));

    if (buildNumber != importBuildNumber) {
      throw new LayoutImportException(
          "LAR build number "
              + importBuildNumber
              + " does not match "
              + "portal build number "
              + buildNumber);
    }

    // Type compatibility

    String type = headerElement.attributeValue("type");

    if (!type.equals("portlet")) {
      throw new LARTypeException("Invalid type of LAR file (" + type + ")");
    }

    // Portlet compatibility

    String rootPortletId = headerElement.attributeValue("root-portlet-id");

    if (!PortletConstants.getRootPortletId(portletId).equals(rootPortletId)) {

      throw new PortletIdException("Invalid portlet id " + rootPortletId);
    }

    // Import group id

    long sourceGroupId = GetterUtil.getLong(headerElement.attributeValue("group-id"));

    portletDataContext.setSourceGroupId(sourceGroupId);

    // Read asset categories, asset tags, comments, locks, and ratings
    // entries to make them available to the data handlers through the
    // context

    if (importPermissions) {
      _permissionImporter.readPortletDataPermissions(portletDataContext);
    }

    readAssetCategories(portletDataContext);
    readAssetTags(portletDataContext);
    readComments(portletDataContext);
    readExpandoTables(portletDataContext);
    readLocks(portletDataContext);
    readRatingsEntries(portletDataContext);

    // Delete portlet data

    if (_log.isDebugEnabled()) {
      _log.debug("Deleting portlet data");
    }

    if (deletePortletData) {
      deletePortletData(portletDataContext, portletId, plid);
    }

    Element portletElement = null;

    try {
      portletElement = rootElement.element("portlet");

      Document portletDocument =
          SAXReaderUtil.read(
              portletDataContext.getZipEntryAsString(portletElement.attributeValue("path")));

      portletElement = portletDocument.getRootElement();
    } catch (DocumentException de) {
      throw new SystemException(de);
    }

    setPortletScope(portletDataContext, portletElement);

    try {

      // Portlet preferences

      importPortletPreferences(
          portletDataContext,
          layout.getCompanyId(),
          groupId,
          layout,
          portletId,
          portletElement,
          importPortletSetup,
          importPortletArchivedSetups,
          importPortletUserPreferences,
          true);

      // Portlet data

      Element portletDataElement = portletElement.element("portlet-data");

      if (importPortletData && (portletDataElement != null)) {
        if (_log.isDebugEnabled()) {
          _log.debug("Importing portlet data");
        }

        importPortletData(portletDataContext, portletId, plid, portletDataElement);
      }
    } finally {
      resetPortletScope(portletDataContext, groupId);
    }

    // Portlet permissions

    if (importPermissions) {
      if (_log.isDebugEnabled()) {
        _log.debug("Importing portlet permissions");
      }

      LayoutCache layoutCache = new LayoutCache();

      _permissionImporter.importPortletPermissions(
          layoutCache,
          layout.getCompanyId(),
          groupId,
          userId,
          layout,
          portletElement,
          portletId,
          importUserPermissions);
    }

    // Asset links

    if (_log.isDebugEnabled()) {
      _log.debug("Importing asset links");
    }

    readAssetLinks(portletDataContext);

    if (_log.isInfoEnabled()) {
      _log.info("Importing portlet takes " + stopWatch.getTime() + " ms");
    }

    zipReader.close();
  }
  protected SyncDLObject updateFileEntries(
      ZipReader zipReader,
      String zipFileId,
      JSONWebServiceActionParametersMap jsonWebServiceActionParametersMap)
      throws Exception {

    ServiceContext serviceContext = new ServiceContext();

    List<NameValue<String, Object>> innerParameters =
        jsonWebServiceActionParametersMap.getInnerParameters("serviceContext");

    if (innerParameters != null) {
      for (NameValue<String, Object> innerParameter : innerParameters) {
        try {
          BeanUtil.setProperty(serviceContext, innerParameter.getName(), innerParameter.getValue());
        } catch (Exception e) {
          if (_log.isDebugEnabled()) {
            _log.debug(e.getMessage(), e);
          }
        }
      }
    }

    String urlPath = MapUtil.getString(jsonWebServiceActionParametersMap, "urlPath");

    if (urlPath.endsWith("/add-file-entry")) {
      long repositoryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "repositoryId");
      long folderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "folderId");
      String sourceFileName =
          MapUtil.getString(jsonWebServiceActionParametersMap, "sourceFileName");
      String mimeType = MapUtil.getString(jsonWebServiceActionParametersMap, "mimeType");
      String title = MapUtil.getString(jsonWebServiceActionParametersMap, "title");
      String description = MapUtil.getString(jsonWebServiceActionParametersMap, "description");
      String changeLog = MapUtil.getString(jsonWebServiceActionParametersMap, "changeLog");

      InputStream inputStream = zipReader.getEntryAsInputStream(zipFileId);

      File tempFile = null;

      try {
        tempFile = FileUtil.createTempFile(inputStream);

        String checksum = MapUtil.getString(jsonWebServiceActionParametersMap, "checksum");

        return addFileEntry(
            repositoryId,
            folderId,
            sourceFileName,
            mimeType,
            title,
            description,
            changeLog,
            tempFile,
            checksum,
            serviceContext);
      } finally {
        FileUtil.delete(tempFile);
      }
    } else if (urlPath.endsWith("/add-folder")) {
      long repositoryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "repositoryId");
      long parentFolderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "parentFolderId");
      String name = MapUtil.getString(jsonWebServiceActionParametersMap, "name");
      String description = MapUtil.getString(jsonWebServiceActionParametersMap, "description");

      return addFolder(repositoryId, parentFolderId, name, description, serviceContext);
    } else if (urlPath.endsWith("/move-file-entry")) {
      long fileEntryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "fileEntryId");
      long newFolderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "newFolderId");

      return moveFileEntry(fileEntryId, newFolderId, serviceContext);
    } else if (urlPath.endsWith("/move-file-entry-to-trash")) {
      long fileEntryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "fileEntryId");

      return moveFileEntryToTrash(fileEntryId);
    } else if (urlPath.endsWith("/move-folder")) {
      long folderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "folderId");
      long parentFolderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "parentFolderId");

      return moveFolder(folderId, parentFolderId, serviceContext);
    } else if (urlPath.endsWith("/move-folder-to-trash")) {
      long folderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "folderId");

      return moveFolderToTrash(folderId);
    } else if (urlPath.endsWith("/patch-file-entry")) {
      long fileEntryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "fileEntryId");
      long sourceVersionId = MapUtil.getLong(jsonWebServiceActionParametersMap, "sourceVersionId");
      String sourceFileName =
          MapUtil.getString(jsonWebServiceActionParametersMap, "sourceFileName");
      String mimeType = MapUtil.getString(jsonWebServiceActionParametersMap, "mimeType");
      String title = MapUtil.getString(jsonWebServiceActionParametersMap, "title");
      String description = MapUtil.getString(jsonWebServiceActionParametersMap, "description");
      String changeLog = MapUtil.getString(jsonWebServiceActionParametersMap, "changeLog");
      boolean majorVersion = MapUtil.getBoolean(jsonWebServiceActionParametersMap, "majorVersion");

      InputStream inputStream = zipReader.getEntryAsInputStream(zipFileId);

      File tempFile = null;

      try {
        tempFile = FileUtil.createTempFile(inputStream);

        String checksum = MapUtil.getString(jsonWebServiceActionParametersMap, "checksum");

        return patchFileEntry(
            fileEntryId,
            sourceVersionId,
            sourceFileName,
            mimeType,
            title,
            description,
            changeLog,
            majorVersion,
            tempFile,
            checksum,
            serviceContext);
      } finally {
        FileUtil.delete(tempFile);
      }
    } else if (urlPath.endsWith("/update-file-entry")) {
      long fileEntryId = MapUtil.getLong(jsonWebServiceActionParametersMap, "fileEntryId");
      String sourceFileName =
          MapUtil.getString(jsonWebServiceActionParametersMap, "sourceFileName");
      String mimeType = MapUtil.getString(jsonWebServiceActionParametersMap, "mimeType");
      String title = MapUtil.getString(jsonWebServiceActionParametersMap, "title");
      String description = MapUtil.getString(jsonWebServiceActionParametersMap, "description");
      String changeLog = MapUtil.getString(jsonWebServiceActionParametersMap, "changeLog");
      boolean majorVersion = MapUtil.getBoolean(jsonWebServiceActionParametersMap, "majorVersion");

      File tempFile = null;

      try {
        InputStream inputStream = zipReader.getEntryAsInputStream(zipFileId);

        if (inputStream != null) {
          tempFile = FileUtil.createTempFile(inputStream);
        }

        String checksum = MapUtil.getString(jsonWebServiceActionParametersMap, "checksum");

        return updateFileEntry(
            fileEntryId,
            sourceFileName,
            mimeType,
            title,
            description,
            changeLog,
            majorVersion,
            tempFile,
            checksum,
            serviceContext);
      } finally {
        FileUtil.delete(tempFile);
      }
    } else if (urlPath.endsWith("/update-folder")) {
      long folderId = MapUtil.getLong(jsonWebServiceActionParametersMap, "folderId");
      String name = MapUtil.getString(jsonWebServiceActionParametersMap, "name");
      String description = MapUtil.getString(jsonWebServiceActionParametersMap, "description");

      return updateFolder(folderId, name, description, serviceContext);
    }

    return null;
  }
  protected void doImportPortletInfo(PortletDataContext portletDataContext, long userId)
      throws Exception {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    boolean importPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();

      serviceContext.setCompanyId(portletDataContext.getCompanyId());
      serviceContext.setSignedIn(false);
      serviceContext.setUserId(userId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    // LAR validation

    validateFile(
        portletDataContext.getCompanyId(),
        portletDataContext.getGroupId(),
        portletDataContext.getPortletId(),
        portletDataContext.getZipReader());

    // Source and target group id

    Map<Long, Long> groupIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(Group.class);

    groupIds.put(portletDataContext.getSourceGroupId(), portletDataContext.getGroupId());

    // Manifest

    ManifestSummary manifestSummary = ExportImportHelperUtil.getManifestSummary(portletDataContext);

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "portlet", portletDataContext.getPortletId(), manifestSummary);
    }

    portletDataContext.setManifestSummary(manifestSummary);

    // Read expando tables, locks and permissions to make them
    // available to the data handlers through the portlet data context

    Element rootElement = portletDataContext.getImportDataRootElement();

    Element portletElement = null;

    try {
      portletElement = rootElement.element("portlet");

      Document portletDocument =
          SAXReaderUtil.read(
              portletDataContext.getZipEntryAsString(portletElement.attributeValue("path")));

      portletElement = portletDocument.getRootElement();
    } catch (DocumentException de) {
      throw new SystemException(de);
    }

    LayoutCache layoutCache = new LayoutCache();

    if (importPermissions) {
      _permissionImporter.checkRoles(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          portletElement);

      _permissionImporter.readPortletDataPermissions(portletDataContext);
    }

    readExpandoTables(portletDataContext);
    readLocks(portletDataContext);

    Element portletDataElement = portletElement.element("portlet-data");

    Map<String, Boolean> importPortletControlsMap =
        ExportImportHelperUtil.getImportPortletControlsMap(
            portletDataContext.getCompanyId(),
            portletDataContext.getPortletId(),
            parameterMap,
            portletDataElement,
            manifestSummary);

    Layout layout = _layoutLocalService.getLayout(portletDataContext.getPlid());

    try {

      // Portlet preferences

      importPortletPreferences(
          portletDataContext,
          layout.getCompanyId(),
          portletDataContext.getGroupId(),
          layout,
          portletElement,
          true,
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));

      // Portlet data

      if (importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA)) {

        if (_log.isDebugEnabled()) {
          _log.debug("Importing portlet data");
        }

        importPortletData(portletDataContext, portletDataElement);
      }
    } finally {
      resetPortletScope(portletDataContext, portletDataContext.getGroupId());
    }

    // Portlet permissions

    if (importPermissions) {
      if (_log.isDebugEnabled()) {
        _log.debug("Importing portlet permissions");
      }

      _permissionImporter.importPortletPermissions(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          layout,
          portletElement,
          portletDataContext.getPortletId());

      if (userId > 0) {
        Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);

        User user = _userLocalService.fetchUser(userId);

        indexer.reindex(user);
      }
    }

    // Asset links

    if (_log.isDebugEnabled()) {
      _log.debug("Importing asset links");
    }

    importAssetLinks(portletDataContext);

    // Deletion system events

    _deletionSystemEventImporter.importDeletionSystemEvents(portletDataContext);

    if (_log.isInfoEnabled()) {
      _log.info("Importing portlet takes " + stopWatch.getTime() + " ms");
    }

    // Service portlet preferences

    boolean importPortletSetup = importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP);

    if (importPortletSetup) {
      try {
        List<Element> serviceElements = rootElement.elements("service");

        for (Element serviceElement : serviceElements) {
          Document serviceDocument =
              SAXReaderUtil.read(
                  portletDataContext.getZipEntryAsString(serviceElement.attributeValue("path")));

          importServicePortletPreferences(portletDataContext, serviceDocument.getRootElement());
        }
      } catch (DocumentException de) {
        throw new SystemException(de);
      }
    }

    ZipReader zipReader = portletDataContext.getZipReader();

    zipReader.close();
  }
  protected void processImages(long userId, WikiNode node, InputStream imagesInputStream)
      throws Exception {

    if (imagesInputStream == null) {
      return;
    }

    ProgressTracker progressTracker = ProgressTrackerThreadLocal.getProgressTracker();

    int count = 0;

    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(imagesInputStream);

    List<String> entries = zipReader.getEntries();

    int total = entries.size();

    if (total > 0) {
      try {
        WikiPageLocalServiceUtil.getPage(node.getNodeId(), SHARED_IMAGES_TITLE);
      } catch (NoSuchPageException nspe) {
        ServiceContext serviceContext = new ServiceContext();

        serviceContext.setAddGroupPermissions(true);
        serviceContext.setAddGuestPermissions(true);

        WikiPageLocalServiceUtil.addPage(
            userId,
            node.getNodeId(),
            SHARED_IMAGES_TITLE,
            SHARED_IMAGES_CONTENT,
            null,
            true,
            serviceContext);
      }
    }

    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
        new ArrayList<ObjectValuePair<String, InputStream>>();

    try {
      int percentage = 50;

      for (int i = 0; i < entries.size(); i++) {
        String entry = entries.get(i);

        String key = entry;

        InputStream inputStream = zipReader.getEntryAsInputStream(entry);

        String[] paths = StringUtil.split(key, CharPool.SLASH);

        if (!isValidImage(paths, inputStream)) {
          if (_log.isInfoEnabled()) {
            _log.info("Ignoring " + key);
          }

          continue;
        }

        String fileName = StringUtil.toLowerCase(paths[paths.length - 1]);

        ObjectValuePair<String, InputStream> inputStreamOVP =
            new ObjectValuePair<String, InputStream>(fileName, inputStream);

        inputStreamOVPs.add(inputStreamOVP);

        count++;

        if ((i % 5) == 0) {
          WikiPageLocalServiceUtil.addPageAttachments(
              userId, node.getNodeId(), SHARED_IMAGES_TITLE, inputStreamOVPs);

          inputStreamOVPs.clear();

          percentage = Math.min(50 + (i * 50) / total, 99);

          progressTracker.setPercent(percentage);
        }
      }

      if (!inputStreamOVPs.isEmpty()) {
        WikiPageLocalServiceUtil.addPageAttachments(
            userId, node.getNodeId(), SHARED_IMAGES_TITLE, inputStreamOVPs);
      }
    } finally {
      for (ObjectValuePair<String, InputStream> inputStreamOVP : inputStreamOVPs) {

        InputStream inputStream = inputStreamOVP.getValue();

        StreamUtil.cleanUp(inputStream);
      }
    }

    zipReader.close();

    if (_log.isInfoEnabled()) {
      _log.info("Imported " + count + " images into " + node.getName());
    }
  }