001package org.apache.commons.jcs3.auxiliary; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.IOException; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.Objects; 026import java.util.Set; 027import java.util.stream.Collectors; 028 029import org.apache.commons.jcs3.engine.behavior.ICacheElement; 030import org.apache.commons.jcs3.engine.behavior.IElementSerializer; 031import org.apache.commons.jcs3.engine.logging.CacheEvent; 032import org.apache.commons.jcs3.engine.logging.behavior.ICacheEvent; 033import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger; 034import org.apache.commons.jcs3.engine.match.KeyMatcherPatternImpl; 035import org.apache.commons.jcs3.engine.match.behavior.IKeyMatcher; 036import org.apache.commons.jcs3.utils.serialization.StandardSerializer; 037 038/** This holds convenience methods used by most auxiliary caches. */ 039public abstract class AbstractAuxiliaryCache<K, V> 040 implements AuxiliaryCache<K, V> 041{ 042 /** An optional event logger */ 043 private ICacheEventLogger cacheEventLogger; 044 045 /** The serializer. Uses a standard serializer by default. */ 046 private IElementSerializer elementSerializer = new StandardSerializer(); 047 048 /** Key matcher used by the getMatching API */ 049 private IKeyMatcher<K> keyMatcher = new KeyMatcherPatternImpl<>(); 050 051 /** 052 * Gets multiple items from the cache based on the given set of keys. 053 * 054 * @param keys 055 * @return a map of K key to ICacheElement<K, V> element, or an empty map if there is no 056 * data in cache for any of these keys 057 */ 058 protected Map<K, ICacheElement<K, V>> processGetMultiple(final Set<K> keys) throws IOException 059 { 060 if (keys != null) 061 { 062 return keys.stream() 063 .map(key -> { 064 try 065 { 066 return get(key); 067 } 068 catch (final IOException e) 069 { 070 return null; 071 } 072 }) 073 .filter(Objects::nonNull) 074 .collect(Collectors.toMap( 075 ICacheElement::getKey, 076 element -> element)); 077 } 078 079 return new HashMap<>(); 080 } 081 082 /** 083 * Gets the item from the cache. 084 * 085 * @param key 086 * @return ICacheElement, a wrapper around the key, value, and attributes 087 * @throws IOException 088 */ 089 @Override 090 public abstract ICacheElement<K, V> get( K key ) throws IOException; 091 092 /** 093 * Logs an event if an event logger is configured. 094 * <p> 095 * @param item 096 * @param eventName 097 * @return ICacheEvent 098 */ 099 protected ICacheEvent<K> createICacheEvent( final ICacheElement<K, V> item, final String eventName ) 100 { 101 if ( cacheEventLogger == null ) 102 { 103 return new CacheEvent<>(); 104 } 105 final String diskLocation = getEventLoggingExtraInfo(); 106 String regionName = null; 107 K key = null; 108 if ( item != null ) 109 { 110 regionName = item.getCacheName(); 111 key = item.getKey(); 112 } 113 return cacheEventLogger.createICacheEvent( getAuxiliaryCacheAttributes().getName(), regionName, eventName, 114 diskLocation, key ); 115 } 116 117 /** 118 * Logs an event if an event logger is configured. 119 * <p> 120 * @param regionName 121 * @param key 122 * @param eventName 123 * @return ICacheEvent 124 */ 125 protected <T> ICacheEvent<T> createICacheEvent( final String regionName, final T key, final String eventName ) 126 { 127 if ( cacheEventLogger == null ) 128 { 129 return new CacheEvent<>(); 130 } 131 final String diskLocation = getEventLoggingExtraInfo(); 132 return cacheEventLogger.createICacheEvent( getAuxiliaryCacheAttributes().getName(), regionName, eventName, 133 diskLocation, key ); 134 135 } 136 137 /** 138 * Logs an event if an event logger is configured. 139 * <p> 140 * @param cacheEvent 141 */ 142 protected <T> void logICacheEvent( final ICacheEvent<T> cacheEvent ) 143 { 144 if ( cacheEventLogger != null ) 145 { 146 cacheEventLogger.logICacheEvent( cacheEvent ); 147 } 148 } 149 150 /** 151 * Logs an event if an event logger is configured. 152 * <p> 153 * @param source 154 * @param eventName 155 * @param optionalDetails 156 */ 157 protected void logApplicationEvent( final String source, final String eventName, final String optionalDetails ) 158 { 159 if ( cacheEventLogger != null ) 160 { 161 cacheEventLogger.logApplicationEvent( source, eventName, optionalDetails ); 162 } 163 } 164 165 /** 166 * Logs an event if an event logger is configured. 167 * <p> 168 * @param source 169 * @param eventName 170 * @param errorMessage 171 */ 172 protected void logError( final String source, final String eventName, final String errorMessage ) 173 { 174 if ( cacheEventLogger != null ) 175 { 176 cacheEventLogger.logError( source, eventName, errorMessage ); 177 } 178 } 179 180 /** 181 * Gets the extra info for the event log. 182 * <p> 183 * @return IP, or disk location, etc. 184 */ 185 public abstract String getEventLoggingExtraInfo(); 186 187 /** 188 * Allows it to be injected. 189 * <p> 190 * @param cacheEventLogger 191 */ 192 @Override 193 public void setCacheEventLogger( final ICacheEventLogger cacheEventLogger ) 194 { 195 this.cacheEventLogger = cacheEventLogger; 196 } 197 198 /** 199 * Allows it to be injected. 200 * <p> 201 * @return cacheEventLogger 202 */ 203 public ICacheEventLogger getCacheEventLogger() 204 { 205 return this.cacheEventLogger; 206 } 207 208 /** 209 * Allows you to inject a custom serializer. A good example would be a compressing standard 210 * serializer. 211 * <p> 212 * Does not allow you to set it to null. 213 * <p> 214 * @param elementSerializer 215 */ 216 @Override 217 public void setElementSerializer( final IElementSerializer elementSerializer ) 218 { 219 if ( elementSerializer != null ) 220 { 221 this.elementSerializer = elementSerializer; 222 } 223 } 224 225 /** 226 * Allows it to be injected. 227 * <p> 228 * @return elementSerializer 229 */ 230 public IElementSerializer getElementSerializer() 231 { 232 return this.elementSerializer; 233 } 234 235 /** 236 * Sets the key matcher used by get matching. 237 * <p> 238 * @param keyMatcher 239 */ 240 @Override 241 public void setKeyMatcher( final IKeyMatcher<K> keyMatcher ) 242 { 243 if ( keyMatcher != null ) 244 { 245 this.keyMatcher = keyMatcher; 246 } 247 } 248 249 /** 250 * Returns the key matcher used by get matching. 251 * <p> 252 * @return keyMatcher 253 */ 254 public IKeyMatcher<K> getKeyMatcher() 255 { 256 return this.keyMatcher; 257 } 258}