Author: johnh
Date: Mon Jan 24 22:49:52 2011
New Revision: 1063048
URL: http://svn.apache.org/viewvc?rev=1063048&view=rev
Log:
Make FeatureJS cache injectable; change key to String from FeatureCacheKey
private object.
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/FeatureRegistry.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/TestFeatureRegistry.java
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/FeatureRegistry.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/FeatureRegistry.java?rev=1063048&r1=1063047&r2=1063048&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/FeatureRegistry.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/FeatureRegistry.java
Mon Jan 24 22:49:52 2011
@@ -18,26 +18,26 @@
package org.apache.shindig.gadgets.features;
import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
-import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
+import org.apache.commons.lang.StringUtils;
import org.apache.shindig.common.Pair;
+import org.apache.shindig.common.cache.Cache;
+import org.apache.shindig.common.cache.CacheProvider;
import org.apache.shindig.common.logging.i18n.MessageKeys;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.common.uri.UriBuilder;
import org.apache.shindig.common.util.ResourceLoader;
import org.apache.shindig.gadgets.GadgetContext;
import org.apache.shindig.gadgets.GadgetException;
-import org.apache.shindig.gadgets.RenderingContext;
import java.io.File;
import java.io.IOException;
@@ -59,6 +59,7 @@ import java.util.logging.Level;
*/
@Singleton
public class FeatureRegistry {
+ public static final String CACHE_NAME = "FeatureJsCache";
public static final String RESOURCE_SCHEME = "res";
public static final String FILE_SCHEME = "file";
public static final Splitter CRLF_SPLITTER =
Splitter.onPattern("[\r\n]+").trimResults().omitEmptyStrings();
@@ -68,7 +69,7 @@ public class FeatureRegistry {
private static final Logger LOG = Logger.getLogger(classname,
MessageKeys.MESSAGES);
// Map keyed by FeatureNode object created as a lookup for transitive
feature deps.
- private final Map<FeatureCacheKey, LookupResult> cache = new
MapMaker().makeMap();
+ private final Cache<String, LookupResult> cache;
private final FeatureParser parser;
private final FeatureResourceLoader resourceLoader;
@@ -86,6 +87,7 @@ public class FeatureRegistry {
*/
@Inject
public FeatureRegistry(FeatureResourceLoader resourceLoader,
+ CacheProvider cacheProvider,
@Named("org.apache.shindig.features") List<String>
features)
throws GadgetException {
this.parser = new FeatureParser();
@@ -96,9 +98,8 @@ public class FeatureRegistry {
// Connect the dependency graph made up of all features and validate there
// are no circular deps.
connectDependencyGraph();
-
- // Clear caches.
- cache.clear();
+
+ this.cache = cacheProvider.createCache(CACHE_NAME);
}
/**
@@ -193,10 +194,13 @@ public class FeatureRegistry {
public LookupResult getFeatureResources(
GadgetContext ctx, Collection<String> needed, List<String> unsupported,
boolean transitive) {
boolean useCache = (transitive && !ctx.getIgnoreCache());
- FeatureCacheKey cacheKey = new FeatureCacheKey(needed, ctx, unsupported !=
null);
+ String cacheKey = makeCacheKey(needed, ctx, unsupported);
- if (useCache && cache.containsKey(cacheKey)) {
- return cache.get(cacheKey);
+ if (useCache) {
+ LookupResult lookup = cache.getElement(cacheKey);
+ if (lookup != null) {
+ return lookup;
+ }
}
List<FeatureNode> featureNodes = transitive ?
@@ -233,7 +237,7 @@ public class FeatureRegistry {
LookupResult result = new LookupResult(bundlesBuilder.build());
if (useCache && (unsupported == null || unsupported.isEmpty())) {
- cache.put(cacheKey, result);
+ cache.addElement(cacheKey, result);
}
return result;
@@ -477,6 +481,16 @@ public class FeatureRegistry {
featureMapBuilder.put(parsed.getName(),
new FeatureNode(parsed.getName(), bundles, parsed.getDeps()));
}
+
+ protected String makeCacheKey(Collection<String> needed, GadgetContext ctx,
List<String> unsupported) {
+ List<String> neededList = Lists.newArrayList(needed);
+ Collections.sort(neededList);
+ return new StringBuilder().append(StringUtils.join(neededList, ":"))
+ .append("|").append(ctx.getRenderingContext().name())
+ .append("|").append(ctx.getContainer())
+ .append("|").append(unsupported != null)
+ .toString();
+ }
private Map<String, String> getResourceAttribs(Map<String, String>
bundleAttribs,
Map<String, String> resourceAttribs) {
@@ -507,7 +521,7 @@ public class FeatureRegistry {
private final List<FeatureBundle> bundles;
private final List<FeatureResource> allResources;
- private LookupResult(List<FeatureBundle> bundles) {
+ public LookupResult(List<FeatureBundle> bundles) {
this.bundles = bundles;
ImmutableList.Builder<FeatureResource> resourcesBuilder =
ImmutableList.builder();
for (FeatureBundle bundle : getBundles()) {
@@ -529,8 +543,8 @@ public class FeatureRegistry {
private final FeatureParser.ParsedFeature.Bundle bundle;
private final List<FeatureResource> resources;
- private FeatureBundle(FeatureParser.ParsedFeature.Bundle bundle,
- List<FeatureResource> resources) {
+ public FeatureBundle(FeatureParser.ParsedFeature.Bundle bundle,
+ List<FeatureResource> resources) {
this.bundle = bundle;
this.resources = ImmutableList.copyOf(resources);
}
@@ -628,39 +642,4 @@ public class FeatureRegistry {
return this.transitiveDeps;
}
}
-
- private static final class FeatureCacheKey {
- private final Collection<String> needed;
- private final RenderingContext rCtx;
- private final String container;
- private final boolean useUnsupported;
-
- private FeatureCacheKey(Collection<String> needed, GadgetContext ctx,
boolean useUnsupported) {
- this.needed = needed;
- this.rCtx = ctx.getRenderingContext();
- this.container = ctx.getContainer();
- this.useUnsupported = useUnsupported;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
- if (!(other instanceof FeatureCacheKey)) {
- return false;
- }
- FeatureCacheKey otherKey = (FeatureCacheKey)other;
- return otherKey.needed.equals(this.needed) &&
- otherKey.rCtx == this.rCtx &&
- otherKey.container.equals(this.container) &&
- otherKey.useUnsupported == this.useUnsupported;
- }
-
- @Override
- public int hashCode() {
- // Doesn't need to be good, just cheap and consistent.
- return Objects.hashCode(needed, rCtx, container, useUnsupported);
- }
- }
}
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/TestFeatureRegistry.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/TestFeatureRegistry.java?rev=1063048&r1=1063047&r2=1063048&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/TestFeatureRegistry.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/features/TestFeatureRegistry.java
Mon Jan 24 22:49:52 2011
@@ -21,6 +21,8 @@ import java.io.IOException;
import java.util.Collections;
import java.util.Map;
+import org.apache.shindig.common.cache.Cache;
+import org.apache.shindig.common.cache.CacheProvider;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.gadgets.GadgetException;
@@ -28,6 +30,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import java.util.List;
@@ -57,6 +60,7 @@ public class TestFeatureRegistry extends
public TestFeatureRegistry build(String useFeature) throws GadgetException
{
return new TestFeatureRegistry(
new TestFeatureResourceLoader(resourceMock),
+ new TestCacheProvider(),
useFeature);
}
@@ -87,17 +91,29 @@ public class TestFeatureRegistry extends
/* Actual class contents here */
private final TestFeatureResourceLoader resourceLoader;
+ private final TestCacheProvider cacheProvider;
private TestFeatureRegistry(
TestFeatureResourceLoader resourceLoader,
+ TestCacheProvider cacheProvider,
String featureFiles) throws GadgetException {
- super(resourceLoader, ImmutableList.<String>of(featureFiles));
+ super(resourceLoader, cacheProvider,
ImmutableList.<String>of(featureFiles));
this.resourceLoader = resourceLoader;
+ this.cacheProvider = cacheProvider;
}
public Map<String, String> getLastAttribs() {
return Collections.unmodifiableMap(resourceLoader.lastAttribs);
}
+ @SuppressWarnings("unchecked")
+ public Cache<String, LookupResult> getLookupCache() {
+ Cache<?, ?> cacheEntry =
cacheProvider.caches.get(FeatureRegistry.CACHE_NAME);
+ if (cacheEntry == null) {
+ return null;
+ }
+ return (Cache<String, LookupResult>)cacheEntry;
+ }
+
private static class TestFeatureResourceLoader extends FeatureResourceLoader
{
private final ResourceMock resourceMock;
private Map<String, String> lastAttribs;
@@ -141,4 +157,45 @@ public class TestFeatureRegistry extends
return key.startsWith("/") ? key.substring(1) : key;
}
}
+
+ // TODO: generalize the below into common classes
+ private static class TestCacheProvider implements CacheProvider {
+ private final Map<String, Cache<?, ?>> caches = new MapMaker().makeMap();
+
+ @SuppressWarnings("unchecked")
+ public <K, V> Cache<K, V> createCache(String name) {
+ Cache<K, V> cache = (Cache<K, V>)caches.get(name);
+ if (cache == null) {
+ cache = new MapCache<K, V>();
+ caches.put(name, cache);
+ }
+ return cache;
+ }
+ }
+
+ private static class MapCache<K, V> implements Cache<K, V> {
+ private final Map<K, V> cache = new MapMaker().makeMap();
+
+ public void addElement(K key, V value) {
+ cache.put(key, value);
+ }
+
+ public long getCapacity() {
+ // Memory-bounded.
+ return Integer.MAX_VALUE;
+ }
+
+ public V getElement(K key) {
+ return cache.get(key);
+ }
+
+ public long getSize() {
+ return cache.size();
+ }
+
+ public V removeElement(K key) {
+ return cache.get(key);
+ }
+
+ }
}