001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.apps.cacheadmin; 029 030import com.alkacon.simapi.Simapi; 031 032import org.opencms.loader.CmsImageLoader; 033import org.opencms.loader.I_CmsImageCache; 034import org.opencms.loader.imagecache.CmsImageCacheEntry; 035import org.opencms.loader.imagecache.CmsImageCacheMaintenanceService; 036import org.opencms.ui.A_CmsUI; 037import org.opencms.util.CmsDateUtil; 038import org.opencms.util.CmsFileUtil; 039 040import java.awt.image.BufferedImage; 041import java.io.ByteArrayOutputStream; 042import java.io.FileInputStream; 043import java.nio.file.Files; 044import java.nio.file.LinkOption; 045import java.nio.file.Paths; 046import java.text.DateFormat; 047import java.time.Instant; 048import java.util.Date; 049 050import org.apache.commons.io.IOUtils; 051 052/** 053 * Bean for Variations im image resources.<p> 054 */ 055public class CmsVariationBean { 056 057 /**Variation path.*/ 058 private String m_variationPath; 059 060 /** The external image cache. */ 061 private I_CmsImageCache m_imageCache; 062 063 /** The variation length. */ 064 private long m_length = -1; 065 066 /** The maintenance service used for lazy metadata access. */ 067 private CmsImageCacheMaintenanceService m_maintenance; 068 069 /** Whether timestamp metadata has been loaded. */ 070 private boolean m_metadataLoaded; 071 072 /** The variation name. */ 073 private String m_name; 074 075 /** The last modification time. */ 076 private Instant m_lastModified; 077 078 /** 079 * Creates a variation bean with lazy metadata access.<p> 080 * 081 * @param imageCache the external image cache 082 * @param maintenance the image cache maintenance service 083 * @param name the image cache entry name 084 * @param length the image cache entry length 085 */ 086 public CmsVariationBean( 087 I_CmsImageCache imageCache, 088 CmsImageCacheMaintenanceService maintenance, 089 String name, 090 long length) { 091 092 m_imageCache = imageCache; 093 m_maintenance = maintenance; 094 m_name = name.startsWith("/") ? name : "/" + name; 095 m_length = length; 096 097 } 098 099 /** 100 * Creates a variation bean for an external image cache entry.<p> 101 * 102 * @param imageCache the external image cache 103 * @param name the image cache entry name 104 * @param length the image cache entry length 105 */ 106 public CmsVariationBean(I_CmsImageCache imageCache, String name, long length) { 107 108 this(imageCache, null, name, length); 109 } 110 111 /** 112 * public constructor.<p> 113 * 114 * @param variation path to variation file to hold information for 115 */ 116 public CmsVariationBean(String variation) { 117 118 m_variationPath = variation; 119 } 120 121 /** Returns the formatted derivative last-modified time, if available. */ 122 public String getDateLastModified() { 123 124 loadMetadata(); 125 return formatDate(m_lastModified); 126 } 127 128 /** 129 * Gets the dimensions of the current variation.<p> 130 * 131 * @return String representation of the dimensions 132 */ 133 public String getDimensions() { 134 135 try { 136 BufferedImage img = Simapi.read(readContent()); 137 return "" + img.getWidth() + " x " + img.getHeight() + "px"; 138 } catch (Exception e) { 139 return ""; 140 } 141 } 142 143 /** 144 * Get length of variation.<p> 145 * 146 * @return string representation of length 147 */ 148 public String getLength() { 149 150 if (m_length >= 0) { 151 return CmsFileUtil.formatFilesize(m_length, A_CmsUI.get().getLocale()); 152 } 153 return CmsFileUtil.formatFilesize(new java.io.File(m_variationPath).length(), A_CmsUI.get().getLocale()); 154 } 155 156 /** 157 * Gets path of variation.<p> 158 * 159 * @return path 160 */ 161 public String getName() { 162 163 if (m_name != null) { 164 return m_name; 165 } 166 String repositoryPath = CmsImageLoader.getImageRepositoryPath(); 167 if ((repositoryPath == null) || !m_variationPath.startsWith(repositoryPath)) { 168 return ""; 169 } 170 return m_variationPath.substring(repositoryPath.length()); 171 } 172 173 /** Formats a timestamp for the current UI locale. */ 174 private String formatDate(Instant timestamp) { 175 176 if (timestamp == null) { 177 return ""; 178 } 179 return CmsDateUtil.getDateTime(Date.from(timestamp), DateFormat.SHORT, A_CmsUI.get().getLocale()); 180 } 181 182 /** Loads timestamp metadata when the variations dialog requests it. */ 183 private synchronized void loadMetadata() { 184 185 if (m_metadataLoaded) { 186 return; 187 } 188 m_metadataLoaded = true; 189 try { 190 if (m_maintenance != null) { 191 CmsImageCacheEntry entry = m_maintenance.getEntry(m_name); 192 if (entry != null) { 193 m_lastModified = entry.getLastModified(); 194 } 195 } else if (m_variationPath != null) { 196 m_lastModified = Files.getLastModifiedTime( 197 Paths.get(m_variationPath), 198 LinkOption.NOFOLLOW_LINKS).toInstant(); 199 } 200 } catch (Exception e) { 201 // The cache entry may have disappeared between listing and opening the dialog. 202 } 203 } 204 205 /** 206 * Reads the variation content.<p> 207 * 208 * @return the variation content 209 * @throws Exception if reading fails 210 */ 211 private byte[] readContent() throws Exception { 212 213 if (m_imageCache != null) { 214 ByteArrayOutputStream out = new ByteArrayOutputStream(); 215 m_imageCache.writeTo(m_name, out); 216 return out.toByteArray(); 217 } 218 try (FileInputStream in = new FileInputStream(m_variationPath)) { 219 return IOUtils.toByteArray(in); 220 } 221 } 222}