001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.favorites; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResourceFilter; 032import org.opencms.file.CmsUser; 033import org.opencms.json.JSONArray; 034import org.opencms.json.JSONException; 035import org.opencms.json.JSONObject; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.util.CmsStringUtil; 040import org.opencms.util.CmsUUID; 041 042import java.util.ArrayList; 043import java.util.Arrays; 044import java.util.HashSet; 045import java.util.List; 046import java.util.Set; 047 048import org.apache.commons.logging.Log; 049 050/** 051 * Loads/saves favorites. 052 * 053 * <p>When loading favorites, the individual entries are validated by trying to read the resources/projects they reference. 054 * If this fails, the entries are discareded from the returned list. 055 */ 056public class CmsFavoriteDAO { 057 058 /** The additional info key under which the favorites for a user are saved. */ 059 public static final String ADDINFO_KEY = "favLocations"; 060 061 /** The main key in the JSON object containing the favorites. */ 062 public static final String BASE_KEY = "f"; 063 064 /** The logger instance for this class. */ 065 private static final Log LOG = CmsLog.getLog(CmsFavoriteDAO.class); 066 067 /** The CMS context. */ 068 private CmsObject m_cms; 069 070 /** Projects which have been validated. */ 071 private Set<CmsUUID> m_okProjects = new HashSet<>(); 072 073 /** Site roots which have been validated. */ 074 private Set<String> m_okSiteRoots = new HashSet<>(); 075 076 /** Structure ids which have been validated. */ 077 private Set<CmsUUID> m_okStructureIds = new HashSet<>(); 078 079 /** The root CMS context. */ 080 private CmsObject m_rootCms; 081 082 /** Name of user from which bookmarks should be loaded. */ 083 private String m_userName; 084 085 /** 086 * Creates a new instance. 087 * 088 * @param cms the CMS Context 089 * @throws CmsException if something goes wrong 090 */ 091 public CmsFavoriteDAO(CmsObject cms) 092 throws CmsException { 093 094 this(cms, cms.getRequestContext().getCurrentUser().getName()); 095 } 096 097 /** 098 * Creates a new instance. 099 * 100 * @param cms the CMS Context 101 * @param userName the name of the user in whose additional infos the bookmarks are stored 102 * @throws CmsException if something goes wrong 103 */ 104 public CmsFavoriteDAO(CmsObject cms, String userName) 105 throws CmsException { 106 107 m_cms = cms; 108 m_rootCms = OpenCms.initCmsObject(m_cms); 109 m_rootCms.getRequestContext().setSiteRoot(""); 110 m_userName = userName; 111 } 112 113 /** 114 * Loads the favorite list. 115 * 116 * @return the list of favorites 117 * 118 * @throws CmsException if something goes wrong 119 */ 120 public List<CmsFavoriteEntry> loadFavorites() throws CmsException { 121 122 List<CmsFavoriteEntry> result = new ArrayList<>(); 123 try { 124 CmsUser user = readUser(); 125 String data = (String)user.getAdditionalInfo(ADDINFO_KEY); 126 if (CmsStringUtil.isEmptyOrWhitespaceOnly(data)) { 127 return new ArrayList<>(); 128 } 129 JSONObject json = new JSONObject(data); 130 JSONArray array = json.getJSONArray(BASE_KEY); 131 for (int i = 0; i < array.length(); i++) { 132 JSONObject fav = array.getJSONObject(i); 133 try { 134 CmsFavoriteEntry entry = new CmsFavoriteEntry(fav); 135 if (validate(entry)) { 136 result.add(entry); 137 } 138 } catch (Exception e) { 139 LOG.warn(e.getLocalizedMessage(), e); 140 } 141 142 } 143 } catch (JSONException e) { 144 LOG.error(e.getLocalizedMessage(), e); 145 } 146 return result; 147 } 148 149 /** 150 * Saves the favorites. 151 * 152 * @param favorites the list of favorites to save 153 * @throws CmsException if something goes wrong 154 */ 155 public void saveFavorites(List<CmsFavoriteEntry> favorites) throws CmsException { 156 157 try { 158 JSONObject json = new JSONObject(); 159 JSONArray array = new JSONArray(); 160 for (CmsFavoriteEntry entry : favorites) { 161 array.put(entry.toJson()); 162 } 163 json.put(BASE_KEY, array); 164 String data = json.toString(); 165 CmsUser user = readUser(); 166 user.setAdditionalInfo(ADDINFO_KEY, data); 167 m_cms.writeUser(user); 168 } catch (JSONException e) { 169 LOG.error(e.getLocalizedMessage(), e); 170 } 171 172 } 173 174 private CmsUser readUser() throws CmsException { 175 176 return m_cms.readUser(m_userName); 177 178 } 179 180 /** 181 * Validates a favorite entry. 182 * 183 * <p>If the favorite entry references a resource or project that can't be read, this will return false. 184 * 185 * @param entry the favorite entry 186 * @return the 187 */ 188 private boolean validate(CmsFavoriteEntry entry) { 189 190 try { 191 String siteRoot = entry.getSiteRoot(); 192 if (!m_okSiteRoots.contains(siteRoot)) { 193 m_rootCms.readResource(siteRoot); 194 m_okSiteRoots.add(siteRoot); 195 } 196 CmsUUID project = entry.getProjectId(); 197 if (!m_okProjects.contains(project)) { 198 m_cms.readProject(project); 199 m_okProjects.add(project); 200 } 201 for (CmsUUID id : Arrays.asList(entry.getDetailId(), entry.getStructureId())) { 202 if ((id != null) && !m_okStructureIds.contains(id)) { 203 m_cms.readResource(id, CmsResourceFilter.IGNORE_EXPIRATION.addRequireVisible()); 204 m_okStructureIds.add(id); 205 } 206 } 207 return true; 208 209 } catch (Exception e) { 210 LOG.info("Favorite entry validation failed: " + e.getLocalizedMessage(), e); 211 return false; 212 } 213 214 } 215 216}