001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH (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; 029 030import com.alkacon.simapi.IdentIcon; 031import com.alkacon.simapi.Simapi; 032 033import org.opencms.cache.CmsVfsNameBasedDiskCache; 034import org.opencms.file.CmsFile; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsProject; 037import org.opencms.file.CmsProperty; 038import org.opencms.file.CmsPropertyDefinition; 039import org.opencms.file.CmsResource; 040import org.opencms.file.CmsResourceFilter; 041import org.opencms.file.CmsUser; 042import org.opencms.file.types.CmsResourceTypeImage; 043import org.opencms.loader.CmsImageScaler; 044import org.opencms.main.CmsException; 045import org.opencms.main.CmsLog; 046import org.opencms.main.OpenCms; 047import org.opencms.security.CmsRole; 048import org.opencms.util.CmsStringUtil; 049import org.opencms.workplace.CmsWorkplace; 050 051import java.awt.Color; 052import java.awt.image.BufferedImage; 053import java.io.IOException; 054import java.util.Collections; 055 056import org.apache.commons.logging.Log; 057 058/** 059 * Generates user ident-icons.<p> 060 */ 061public class CmsUserIconHelper { 062 063 /** The color reserved for admin users. */ 064 public static final Color ADMIN_COLOR = new Color(0x00, 0x30, 0x82); 065 066 /** The big icon suffix. */ 067 public static final String BIG_ICON_SUFFIX = "_big_icon.png"; 068 069 /** The target folder name. */ 070 public static final String ICON_FOLDER = "user_icons"; 071 072 /** The small icon suffix. */ 073 public static final String SMALL_ICON_SUFFIX = "_small_icon.png"; 074 075 /** The temp folder name. */ 076 public static final String TEMP_FOLDER = "temp/"; 077 078 /** The user image folder. */ 079 public static final String USER_IMAGE_FOLDER = "/system/userimages/"; 080 081 /** The user image additional info key. */ 082 public static final String USER_IMAGE_INFO = "USER_IMAGE"; 083 084 /** Logger instance for this class. */ 085 private static final Log LOG = CmsLog.getLog(CmsUserIconHelper.class); 086 087 /** The admin cms context. */ 088 private CmsObject m_adminCms; 089 090 /** The image cache. */ 091 private CmsVfsNameBasedDiskCache m_cache; 092 093 /** The icon renderer. */ 094 private IdentIcon m_renderer; 095 096 /** 097 * Constructor.<p> 098 * 099 * @param adminCms the admin cms context 100 */ 101 public CmsUserIconHelper(CmsObject adminCms) { 102 m_adminCms = adminCms; 103 m_renderer = new IdentIcon(); 104 m_renderer.setReservedColor(ADMIN_COLOR); 105 106 m_cache = new CmsVfsNameBasedDiskCache( 107 OpenCms.getSystemInfo().getWebApplicationRfsPath() + "/" + CmsWorkplace.RFS_PATH_RESOURCES, 108 ICON_FOLDER); 109 } 110 111 /** 112 * Returns the big ident-icon path for the given user.<p> 113 * 114 * @param cms the cms context 115 * @param user the user 116 * 117 * @return the icon path 118 */ 119 public String getBigIconPath(CmsObject cms, CmsUser user) { 120 121 return getIconPath(cms, user, true); 122 } 123 124 /** 125 * Returns the small ident-icon path for the given user.<p> 126 * 127 * @param cms the cms context 128 * @param user the user 129 * 130 * @return the icon path 131 */ 132 public String getSmallIconPath(CmsObject cms, CmsUser user) { 133 134 return getIconPath(cms, user, false); 135 } 136 137 /** 138 * Handles a user image upload. 139 * The uploaded file will be scaled and save as a new file beneath /system/userimages/, the original file will be deleted.<p> 140 * 141 * @param cms the cms context 142 * @param user the user 143 * @param uploadedFile the uploaded file 144 */ 145 public void handleImageUpload(CmsObject cms, CmsUser user, String uploadedFile) { 146 147 try { 148 setUserImage(cms, user, uploadedFile); 149 150 } catch (CmsException e) { 151 LOG.error("Error setting user image.", e); 152 } 153 try { 154 cms.lockResource(uploadedFile); 155 cms.deleteResource(uploadedFile, CmsResource.DELETE_REMOVE_SIBLINGS); 156 } catch (CmsException e) { 157 LOG.error("Error deleting user image temp file.", e); 158 } 159 } 160 161 /** 162 * Sets the user image for the given user.<p> 163 * 164 * @param cms the cms context 165 * @param user the user 166 * @param rootPath the image root path 167 * 168 * @throws CmsException in case anything goes wrong 169 */ 170 public void setUserImage(CmsObject cms, CmsUser user, String rootPath) throws CmsException { 171 172 CmsFile tempFile = cms.readFile(cms.getRequestContext().removeSiteRoot(rootPath)); 173 CmsImageScaler scaler = new CmsImageScaler(tempFile.getContents(), tempFile.getRootPath()); 174 175 if (scaler.isValid()) { 176 scaler.setType(2); 177 scaler.setHeight(192); 178 scaler.setWidth(192); 179 byte[] content = scaler.scaleImage(tempFile); 180 String previousImage = null; 181 String newFileName = USER_IMAGE_FOLDER 182 + user.getId().toString() 183 + "_" 184 + System.currentTimeMillis() 185 + getSuffix(tempFile.getName()); 186 CmsObject adminCms = OpenCms.initCmsObject(m_adminCms); 187 CmsProject tempProject = adminCms.createTempfileProject(); 188 adminCms.getRequestContext().setCurrentProject(tempProject); 189 if (adminCms.existsResource(newFileName)) { 190 // a user image of the given name already exists, just write the new content 191 CmsFile imageFile = adminCms.readFile(newFileName); 192 adminCms.lockResource(imageFile); 193 imageFile.setContents(content); 194 adminCms.writeFile(imageFile); 195 adminCms.writePropertyObject( 196 newFileName, 197 new CmsProperty(CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, null, "w:192,h:192")); 198 } else { 199 previousImage = (String)user.getAdditionalInfo(CmsUserIconHelper.USER_IMAGE_INFO); 200 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(previousImage) 201 && cms.existsResource(newFileName, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 202 try { 203 adminCms.lockResource(previousImage); 204 adminCms.deleteResource(previousImage, CmsResource.DELETE_REMOVE_SIBLINGS); 205 } catch (CmsException e) { 206 LOG.error("Error deleting previous user image.", e); 207 } 208 } 209 // create a new user image file 210 adminCms.createResource( 211 newFileName, 212 OpenCms.getResourceManager().getResourceType(CmsResourceTypeImage.getStaticTypeName()), 213 content, 214 Collections.singletonList( 215 new CmsProperty(CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, null, "w:192,h:192"))); 216 } 217 user.setAdditionalInfo(CmsUserIconHelper.USER_IMAGE_INFO, newFileName); 218 adminCms.writeUser(user); 219 220 try { 221 OpenCms.getPublishManager().publishProject(adminCms); 222 } catch (Exception e) { 223 LOG.error("Error publishing user image resources.", e); 224 } 225 226 } 227 } 228 229 /** 230 * Returns the ident-icon path for the given user.<p> 231 * 232 * @param cms the cms context 233 * @param user the user 234 * @param big <code>true</code> to retrieve the big icon 235 * 236 * @return the icon path 237 */ 238 private String getIconPath(CmsObject cms, CmsUser user, boolean big) { 239 240 String userIconPath = (String)user.getAdditionalInfo(USER_IMAGE_INFO); 241 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(userIconPath)) { 242 userIconPath += big ? "" : "?__scale=h:32,w:32,t:2"; 243 return OpenCms.getLinkManager().substituteLinkForRootPath(cms, userIconPath); 244 } 245 246 boolean isAdmin = OpenCms.getRoleManager().hasRole(cms, user.getName(), CmsRole.ADMINISTRATOR); 247 String name = user.getName() + Boolean.toString(isAdmin); 248 String rfsName = toRfsName(name, big); 249 String path = toPath(name, big); 250 if (!m_cache.hasCacheContent(rfsName)) { 251 252 BufferedImage icon = m_renderer.render(name, isAdmin, big ? 96 : 32); 253 try { 254 m_cache.saveCacheFile(rfsName, getImageBytes(icon)); 255 } catch (Exception e) { 256 LOG.error(e.getLocalizedMessage(), e); 257 } 258 } 259 return path; 260 } 261 262 /** 263 * Returns the image data 264 * @param image the image 265 * 266 * @return the data 267 * 268 * @throws IOException in case writing to the output stream failed 269 */ 270 private byte[] getImageBytes(BufferedImage image) throws IOException { 271 272 return Simapi.getImageBytes(image, Simapi.TYPE_PNG); 273 } 274 275 /** 276 * Returns the file suffix.<p> 277 * 278 * @param fileName the file name 279 * 280 * @return the suffix 281 */ 282 private String getSuffix(String fileName) { 283 284 int index = fileName.lastIndexOf("."); 285 if (index > 0) { 286 return fileName.substring(index); 287 } else { 288 return fileName; 289 } 290 } 291 292 /** 293 * Transforms user name and icon size into the image path. 294 * 295 * @param name the user name 296 * @param big <code>true</code> in case of big icons 297 * 298 * @return the path 299 */ 300 private String toPath(String name, boolean big) { 301 302 String result = CmsStringUtil.joinPaths(CmsWorkplace.getSkinUri(), ICON_FOLDER, "" + name.hashCode()); 303 if (big) { 304 result += BIG_ICON_SUFFIX; 305 } else { 306 result += SMALL_ICON_SUFFIX; 307 } 308 return result; 309 } 310 311 /** 312 * Transforms user name and icon size into the rfs image path. 313 * 314 * @param name the user name 315 * @param big <code>true</code> in case of big icons 316 * 317 * @return the path 318 */ 319 private String toRfsName(String name, boolean big) { 320 321 String result = CmsStringUtil.joinPaths(m_cache.getRepositoryPath(), "" + name.hashCode()); 322 if (big) { 323 result += BIG_ICON_SUFFIX; 324 } else { 325 result += SMALL_ICON_SUFFIX; 326 } 327 return result; 328 } 329}