001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.request.resource.caching.version; 018 019import java.io.Serializable; 020import java.util.Map; 021import java.util.regex.Pattern; 022 023import org.apache.wicket.MetaDataKey; 024import org.apache.wicket.ThreadContext; 025import org.apache.wicket.request.cycle.RequestCycle; 026import org.apache.wicket.request.resource.caching.IStaticCacheableResource; 027import org.apache.wicket.util.lang.Args; 028import org.apache.wicket.util.lang.Generics; 029 030/** 031 * Caches the results of a delegating {@link IResourceVersion} instance 032 * for the lifetime of the current http request. 033 * 034 * @author Peter Ertl 035 * 036 * @since 1.5 037 */ 038public class RequestCycleCachedResourceVersion implements IResourceVersion 039{ 040 private static final MetaDataKey<Map<Serializable, String>> CACHE_KEY = 041 new MetaDataKey<>() 042 { 043 private static final long serialVersionUID = 1L; 044 }; 045 046 /** 047 * resource version provider which will actually do 048 * the hard work and retrieve the version 049 */ 050 private final IResourceVersion delegate; 051 052 /** 053 * create request-scoped resource provider cache 054 * 055 * @param delegate 056 * resource version provider to cache 057 */ 058 public RequestCycleCachedResourceVersion(IResourceVersion delegate) 059 { 060 this.delegate = Args.notNull(delegate, "delegate"); 061 } 062 063 @Override 064 public String getVersion(IStaticCacheableResource resource) 065 { 066 // get current request cycle 067 final RequestCycle requestCycle = ThreadContext.getRequestCycle(); 068 069 // cache instance 070 Map<Serializable, String> cache = null; 071 072 // cache key 073 Serializable key = null; 074 075 // is request cycle available? 076 if (requestCycle != null) 077 { 078 // retrieve cache from current request cycle 079 cache = requestCycle.getMetaData(CACHE_KEY); 080 081 // create caching key 082 key = resource.getCacheKey(); 083 084 // does cache exist within current request cycle? 085 if (cache == null) 086 { 087 // no, so create it 088 requestCycle.setMetaData(CACHE_KEY, cache = Generics.newHashMap()); 089 } 090 else if (cache.containsKey(key)) 091 { 092 // lookup timestamp from cache (may contain NULL values which are valid) 093 return cache.get(key); 094 } 095 } 096 097 // no cache entry found, query version from delegate 098 final String version = delegate.getVersion(resource); 099 100 // store value in cache (if it is available) 101 if (cache != null && key != null) 102 { 103 cache.put(key, version); 104 } 105 106 return version; 107 } 108 109 @Override 110 public Pattern getVersionPattern() 111 { 112 return delegate.getVersionPattern(); 113 } 114}