private Set<String> _readThemes(
      String servletContextName,
      ServletContext servletContext,
      String themesPath,
      boolean loadFromServletContext,
      String xml,
      PluginPackage pluginPackage)
      throws Exception {

    Set<String> themeIds = new HashSet<String>();

    if (xml == null) {
      return themeIds;
    }

    Document doc = SAXReaderUtil.read(xml, true);

    Element root = doc.getRootElement();

    Version portalVersion = _getVersion(ReleaseInfo.getVersion());

    boolean compatible = false;

    Element compatibilityEl = root.element("compatibility");

    if (compatibilityEl != null) {
      Iterator<Element> itr = compatibilityEl.elements("version").iterator();

      while (itr.hasNext()) {
        Element versionEl = itr.next();

        Version version = _getVersion(versionEl.getTextTrim());

        if (version.includes(portalVersion)) {
          compatible = true;

          break;
        }
      }
    }

    if (!compatible) {
      _log.error("Themes in this WAR are not compatible with " + ReleaseInfo.getServerInfo());

      return themeIds;
    }

    ThemeCompanyLimit companyLimit = null;

    Element companyLimitEl = root.element("company-limit");

    if (companyLimitEl != null) {
      companyLimit = new ThemeCompanyLimit();

      Element companyIncludesEl = companyLimitEl.element("company-includes");

      if (companyIncludesEl != null) {
        companyLimit.setIncludes(_getCompanyLimitIncludes(companyIncludesEl));
      }

      Element companyExcludesEl = companyLimitEl.element("company-excludes");

      if (companyExcludesEl != null) {
        companyLimit.setExcludes(_getCompanyLimitExcludes(companyExcludesEl));
      }
    }

    ThemeGroupLimit groupLimit = null;

    Element groupLimitEl = root.element("group-limit");

    if (groupLimitEl != null) {
      groupLimit = new ThemeGroupLimit();

      Element groupIncludesEl = groupLimitEl.element("group-includes");

      if (groupIncludesEl != null) {
        groupLimit.setIncludes(_getGroupLimitIncludes(groupIncludesEl));
      }

      Element groupExcludesEl = groupLimitEl.element("group-excludes");

      if (groupExcludesEl != null) {
        groupLimit.setExcludes(_getGroupLimitExcludes(groupExcludesEl));
      }
    }

    long timestamp = ServletContextUtil.getLastModified(servletContext);

    Iterator<Element> itr1 = root.elements("theme").iterator();

    while (itr1.hasNext()) {
      Element theme = itr1.next();

      ContextReplace themeContextReplace = new ContextReplace();

      themeContextReplace.addValue("themes-path", themesPath);

      String themeId = theme.attributeValue("id");

      if (servletContextName != null) {
        themeId = themeId + PortletConstants.WAR_SEPARATOR + servletContextName;
      }

      themeId = PortalUtil.getJsSafePortletId(themeId);

      themeContextReplace.addValue("theme-id", themeId);

      themeIds.add(themeId);

      Theme themeModel = _themes.get(themeId);

      if (themeModel == null) {
        themeModel = new ThemeImpl(themeId);

        _themes.put(themeId, themeModel);
      }

      themeModel.setTimestamp(timestamp);

      PluginSetting pluginSetting = pluginSettingLocalService.getDefaultPluginSetting();

      themeModel.setPluginPackage(pluginPackage);
      themeModel.setDefaultPluginSetting(pluginSetting);

      themeModel.setThemeCompanyLimit(companyLimit);
      themeModel.setThemeGroupLimit(groupLimit);

      if (servletContextName != null) {
        themeModel.setServletContextName(servletContextName);
      }

      themeModel.setLoadFromServletContext(loadFromServletContext);

      String name = GetterUtil.getString(theme.attributeValue("name"), themeModel.getName());

      String rootPath =
          GetterUtil.getString(theme.elementText("root-path"), themeModel.getRootPath());

      rootPath = themeContextReplace.replace(rootPath);

      themeContextReplace.addValue("root-path", rootPath);

      String templatesPath =
          GetterUtil.getString(theme.elementText("templates-path"), themeModel.getTemplatesPath());

      templatesPath = themeContextReplace.replace(templatesPath);
      templatesPath = StringUtil.safePath(templatesPath);

      themeContextReplace.addValue("templates-path", templatesPath);

      String cssPath = GetterUtil.getString(theme.elementText("css-path"), themeModel.getCssPath());

      cssPath = themeContextReplace.replace(cssPath);
      cssPath = StringUtil.safePath(cssPath);

      themeContextReplace.addValue("css-path", cssPath);

      String imagesPath =
          GetterUtil.getString(theme.elementText("images-path"), themeModel.getImagesPath());

      imagesPath = themeContextReplace.replace(imagesPath);
      imagesPath = StringUtil.safePath(imagesPath);

      themeContextReplace.addValue("images-path", imagesPath);

      String javaScriptPath =
          GetterUtil.getString(
              theme.elementText("javascript-path"), themeModel.getJavaScriptPath());

      javaScriptPath = themeContextReplace.replace(javaScriptPath);
      javaScriptPath = StringUtil.safePath(javaScriptPath);

      themeContextReplace.addValue("javascript-path", javaScriptPath);

      String virtualPath =
          GetterUtil.getString(theme.elementText("virtual-path"), themeModel.getVirtualPath());

      String templateExtension =
          GetterUtil.getString(
              theme.elementText("template-extension"), themeModel.getTemplateExtension());

      themeModel.setName(name);
      themeModel.setRootPath(rootPath);
      themeModel.setTemplatesPath(templatesPath);
      themeModel.setCssPath(cssPath);
      themeModel.setImagesPath(imagesPath);
      themeModel.setJavaScriptPath(javaScriptPath);
      themeModel.setVirtualPath(virtualPath);
      themeModel.setTemplateExtension(templateExtension);

      Element settingsEl = theme.element("settings");

      if (settingsEl != null) {
        Iterator<Element> itr2 = settingsEl.elements("setting").iterator();

        while (itr2.hasNext()) {
          Element settingEl = itr2.next();

          String key = settingEl.attributeValue("key");
          String value = settingEl.attributeValue("value");

          themeModel.setSetting(key, value);
        }
      }

      themeModel.setWapTheme(
          GetterUtil.getBoolean(theme.elementText("wap-theme"), themeModel.isWapTheme()));

      Element rolesEl = theme.element("roles");

      if (rolesEl != null) {
        Iterator<Element> itr2 = rolesEl.elements("role-name").iterator();

        while (itr2.hasNext()) {
          Element roleNameEl = itr2.next();

          pluginSetting.addRole(roleNameEl.getText());
        }
      }

      _readColorSchemes(theme, themeModel.getColorSchemesMap(), themeContextReplace);
      _readColorSchemes(theme, themeModel.getColorSchemesMap(), themeContextReplace);

      Element layoutTemplatesEl = theme.element("layout-templates");

      if (layoutTemplatesEl != null) {
        Element standardEl = layoutTemplatesEl.element("standard");

        if (standardEl != null) {
          layoutTemplateLocalService.readLayoutTemplate(
              servletContextName, servletContext, null, standardEl, true, themeId, pluginPackage);
        }

        Element customEl = layoutTemplatesEl.element("custom");

        if (customEl != null) {
          layoutTemplateLocalService.readLayoutTemplate(
              servletContextName, servletContext, null, customEl, false, themeId, pluginPackage);
        }
      }

      if (!themeModel.isWapTheme()) {
        _setSpriteImages(servletContext, themeModel, imagesPath);
      }
    }

    return themeIds;
  }