001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.cache.tag; 020 021import java.io.IOException; 022import java.util.HashMap; 023import java.util.Map; 024 025import lucee.commons.digest.HashUtil; 026import lucee.commons.lang.KeyGenerator; 027import lucee.runtime.PageContext; 028import lucee.runtime.PageSource; 029import lucee.runtime.cache.tag.request.RequestCacheHandler; 030import lucee.runtime.cache.tag.timespan.TimespanCacheHandler; 031import lucee.runtime.cache.tag.udf.UDFArgConverter; 032import lucee.runtime.config.Config; 033import lucee.runtime.config.ConfigImpl; 034import lucee.runtime.db.SQL; 035import lucee.runtime.exp.PageException; 036import lucee.runtime.functions.cache.Util; 037import lucee.runtime.op.Caster; 038import lucee.runtime.type.Struct; 039import lucee.runtime.type.UDF; 040import lucee.runtime.type.util.KeyConstants; 041 042public class CacheHandlerFactory { 043 044 public static final int TYPE_TIMESPAN=1; 045 public static final int TYPE_REQUEST=2; 046 047 public static final char CACHE_DEL = ';'; 048 public static final char CACHE_DEL2 = ':'; 049 050 051 final RequestCacheHandler rch; 052 private Map<Config,TimespanCacheHandler> tschs=new HashMap<Config, TimespanCacheHandler>(); 053 private int cacheDefaultType; 054 055 protected CacheHandlerFactory(int cacheDefaultType) { 056 this.cacheDefaultType=cacheDefaultType; 057 rch=new RequestCacheHandler(cacheDefaultType); 058 } 059 060 /** 061 * based on the cachedWithin Object we choose the right Cachehandler and return it 062 * @return 063 */ 064 public CacheHandler getInstance(Config config,Object cachedWithin){ 065 if(Caster.toTimespan(cachedWithin,null)!=null) { 066 return getTimespanCacheHandler(config); 067 } 068 String str=Caster.toString(cachedWithin,"").trim(); 069 if("request".equalsIgnoreCase(str)) return rch; 070 071 return null; 072 } 073 074 public CacheHandler getInstance(Config config,int type){ 075 if(TYPE_TIMESPAN==type)return getTimespanCacheHandler(config); 076 if(TYPE_REQUEST==type) return rch; 077 return null; 078 } 079 080 private CacheHandler getTimespanCacheHandler(Config config) { 081 TimespanCacheHandler tsch = tschs.get(config); 082 if(tsch==null) { 083 tschs.put(config, tsch=new TimespanCacheHandler(cacheDefaultType, null)); 084 } 085 return tsch; 086 } 087 088 public int size(PageContext pc) throws PageException { 089 int size=rch.size(pc); 090 size+=getTimespanCacheHandler(pc.getConfig()).size(pc); 091 return size; 092 } 093 094 095 public void clear(PageContext pc) throws PageException { 096 rch.clear(pc); 097 getTimespanCacheHandler(pc.getConfig()).clear(pc); 098 } 099 100 public void clear(PageContext pc, CacheHandlerFilter filter) throws PageException { 101 rch.clear(pc,filter); 102 getTimespanCacheHandler(pc.getConfig()).clear(pc,filter); 103 } 104 105 public void clean(PageContext pc) throws PageException { 106 rch.clean(pc); 107 getTimespanCacheHandler(pc.getConfig()).clean(pc); 108 } 109 110 public static String createId(PageSource[] sources) throws PageException{ 111 String str; 112 if(sources.length==1) { 113 str= sources[0].getDisplayPath(); 114 } 115 else { 116 StringBuilder sb=new StringBuilder(); 117 for(int i=0;i<sources.length;i++){ 118 if(i>0)sb.append(";"); 119 sb.append(sources[i].getDisplayPath()); 120 } 121 str=sb.toString(); 122 } 123 try { 124 return Util.key(KeyGenerator.createKey(str)); 125 } 126 catch (IOException e) { 127 throw Caster.toPageException(e); 128 } 129 } 130 131 public static String createId(SQL sql, String datasource, String username,String password) throws PageException{ 132 try { 133 return Util.key(KeyGenerator.createKey(sql.toHashString()+datasource+username+password)); 134 } 135 catch (IOException e) { 136 throw Caster.toPageException(e); 137 } 138 } 139 140 public static String createId(UDF udf, Object[] args, Struct values) { 141 StringBuilder sb=new StringBuilder() 142 .append(HashUtil.create64BitHash(udf.getPageSource().getDisplayPath())) 143 .append(CACHE_DEL) 144 .append(HashUtil.create64BitHash(udf.getFunctionName())) 145 .append(CACHE_DEL); 146 147 148 149 if(values!=null) { 150 // argumentCollection 151 Struct sct; 152 if(values.size()==1 && (sct=Caster.toStruct(values.get(KeyConstants._argumentCollection,null),null))!=null) { 153 sb.append(_createId(sct)); 154 } 155 else sb.append(_createId(values)); 156 } 157 else if(args!=null){ 158 sb.append(_createId(args)); 159 } 160 return HashUtil.create64BitHashAsString(sb, Character.MAX_RADIX); 161 } 162 163 private static String _createId(Object values) { 164 return HashUtil.create64BitHash(UDFArgConverter.serialize(values))+""; 165 } 166 167 168 public static String toStringType(int type, String defaultValue) { 169 switch(type){ 170 case TYPE_REQUEST: return "request"; 171 case TYPE_TIMESPAN: return "timespan"; 172 } 173 return defaultValue; 174 } 175 176 public static String toStringCacheName(int type, String defaultValue) { 177 switch(type){ 178 case ConfigImpl.CACHE_DEFAULT_FUNCTION: return "function"; 179 case ConfigImpl.CACHE_DEFAULT_INCLUDE: return "include"; 180 case ConfigImpl.CACHE_DEFAULT_OBJECT: return "object"; 181 case ConfigImpl.CACHE_DEFAULT_QUERY: return "query"; 182 case ConfigImpl.CACHE_DEFAULT_RESOURCE: return "resource"; 183 case ConfigImpl.CACHE_DEFAULT_TEMPLATE: return "template"; 184 } 185 return defaultValue; 186 } 187 188 public static CacheItem toCacheItem(Object value, CacheItem defaultValue) { 189 if(value instanceof CacheItem) return (CacheItem) value; 190 return defaultValue; 191 } 192}