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);
+    }
+    
+  }
 }


Reply via email to