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 GmbH & Co. KG, 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.loader.imagecache; 029 030import org.opencms.configuration.CmsImageCacheConfiguration; 031import org.opencms.configuration.CmsImageCacheConfiguration.RetentionMode; 032import org.opencms.loader.CmsFsImageCache; 033import org.opencms.loader.CmsImageLoader; 034import org.opencms.loader.CmsRfsImageCache; 035import org.opencms.loader.CmsS3ImageCache; 036import org.opencms.loader.I_CmsImageCache; 037import org.opencms.loader.imagecache.CmsImageCacheCapabilities.Capability; 038import org.opencms.main.OpenCms; 039 040import java.util.Objects; 041 042/** 043 * Capability-aware entry point for image cache maintenance clients.<p> 044 */ 045public final class CmsImageCacheMaintenanceService { 046 047 /** The maintenance backend. */ 048 private final I_CmsImageCacheMaintenance m_backend; 049 050 /** 051 * Creates a maintenance service.<p> 052 * 053 * @param backend the maintenance backend 054 */ 055 public CmsImageCacheMaintenanceService(I_CmsImageCacheMaintenance backend) { 056 057 m_backend = Objects.requireNonNull(backend, "backend"); 058 } 059 060 /** 061 * Creates a service for an image cache implementation.<p> 062 * 063 * @param cache the image cache 064 * @return the maintenance service 065 */ 066 public static CmsImageCacheMaintenanceService create(I_CmsImageCache cache) { 067 068 Objects.requireNonNull(cache, "cache"); 069 if (cache instanceof CmsFsImageCache) { 070 return new CmsImageCacheMaintenanceService(new CmsFsImageCacheMaintenance((CmsFsImageCache)cache)); 071 } 072 if (cache instanceof CmsS3ImageCache) { 073 return new CmsImageCacheMaintenanceService(new CmsS3ImageCacheMaintenance((CmsS3ImageCache)cache)); 074 } 075 if (cache instanceof CmsRfsImageCache) { 076 return new CmsImageCacheMaintenanceService(new CmsRfsImageCacheMaintenance((CmsRfsImageCache)cache)); 077 } 078 throw new IllegalArgumentException("Unsupported image cache implementation: " + cache.getClass().getName()); 079 } 080 081 /** 082 * Creates a service using the central image cache maintenance configuration.<p> 083 * 084 * @param cache the image cache 085 * @param configuration the image cache configuration 086 * @return the maintenance service 087 */ 088 public static CmsImageCacheMaintenanceService create( 089 I_CmsImageCache cache, 090 CmsImageCacheConfiguration configuration) { 091 092 Objects.requireNonNull(cache, "cache"); 093 Objects.requireNonNull(configuration, "configuration"); 094 if (cache instanceof CmsFsImageCache) { 095 return new CmsImageCacheMaintenanceService( 096 new CmsFsImageCacheMaintenance( 097 (CmsFsImageCache)cache, 098 configuration.getRetentionMode() == RetentionMode.renewOnUse, 099 configuration.getFsTouchConcurrency())); 100 } 101 if (cache instanceof CmsS3ImageCache) { 102 return new CmsImageCacheMaintenanceService( 103 new CmsS3ImageCacheMaintenance( 104 (CmsS3ImageCache)cache, 105 configuration.getS3DeleteBatchSize(), 106 configuration.getS3DeleteConcurrency(), 107 configuration.getS3CopyConcurrency(), 108 configuration.getS3MaxCopiesPerSecond(), 109 configuration.getS3RenewalQueueCapacity())); 110 } 111 return create(cache); 112 } 113 114 /** 115 * Creates a service for the image cache currently configured in the image loader.<p> 116 * 117 * @return the maintenance service 118 * @throws Exception if the configured cache can not be accessed 119 */ 120 public static CmsImageCacheMaintenanceService createForConfiguredCache() throws Exception { 121 122 I_CmsImageCache imageCache = CmsImageLoader.getImageCache(); 123 if (imageCache != null) { 124 return create(imageCache, OpenCms.getImageCacheConfiguration()); 125 } 126 String repositoryPath = CmsImageLoader.getImageRepositoryPath(); 127 if (repositoryPath != null) { 128 return createForRfsRepository(repositoryPath); 129 } 130 throw new IllegalStateException("No image cache repository is configured."); 131 } 132 133 /** 134 * Creates a service for the classic RFS image cache repository.<p> 135 * 136 * @param repositoryPath the repository path 137 * @return the maintenance service 138 * @throws Exception if the repository can not be initialized 139 */ 140 public static CmsImageCacheMaintenanceService createForRfsRepository(String repositoryPath) throws Exception { 141 142 return create(new CmsRfsImageCache(repositoryPath)); 143 } 144 145 /** 146 * Executes a maintenance request after checking backend capabilities.<p> 147 * 148 * @param request the request 149 * @return the result 150 * @throws Exception if execution fails 151 */ 152 public CmsImageCacheMaintenanceResult execute(CmsImageCacheMaintenanceRequest request) throws Exception { 153 154 Capability capability; 155 switch (request.getOperation()) { 156 case CLEAR: 157 capability = Capability.CLEAR; 158 break; 159 case DELETE: 160 capability = Capability.DELETE_ENTRIES; 161 break; 162 case RENEW: 163 capability = Capability.RENEW_ENTRIES; 164 break; 165 default: 166 throw new IllegalArgumentException( 167 "Unsupported image cache maintenance operation: " + request.getOperation()); 168 } 169 requireCapability(capability); 170 return m_backend.execute(request); 171 } 172 173 /** Returns the backend identifier. */ 174 public String getBackendId() { 175 176 return m_backend.getBackendId(); 177 } 178 179 /** Returns the backend capabilities. */ 180 public CmsImageCacheCapabilities getCapabilities() { 181 182 return m_backend.getCapabilities(); 183 } 184 185 /** 186 * Loads metadata for one cache entry.<p> 187 * 188 * @param key the image cache key 189 * @return the entry metadata, or {@code null} if the entry does not exist 190 * @throws Exception if the metadata can not be loaded 191 */ 192 public CmsImageCacheEntry getEntry(String key) throws Exception { 193 194 requireCapability(Capability.LIST_ENTRIES); 195 return m_backend.getEntry(key); 196 } 197 198 /** 199 * Streams all cache entries.<p> 200 * 201 * @param visitor the visitor 202 * @throws Exception if listing fails 203 */ 204 public void visitEntries(I_CmsImageCacheMaintenanceEntryVisitor visitor) throws Exception { 205 206 requireCapability(Capability.LIST_ENTRIES); 207 m_backend.visitEntries(visitor); 208 } 209 210 /** Ensures that a backend capability is available. */ 211 private void requireCapability(Capability capability) { 212 213 if (!m_backend.getCapabilities().supports(capability)) { 214 throw new UnsupportedOperationException( 215 "Image cache backend " + m_backend.getBackendId() + " does not support " + capability + "."); 216 } 217 } 218}