[gatein-commits] gatein SVN: r2492 - in portal/branches/EPP_5_0_Branch/component: common/src/main/java/org/exoplatform/commons/cache/future and 5 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Apr 6 09:32:15 EDT 2010


Author: mpodolin
Date: 2010-04-06 09:32:13 -0400 (Tue, 06 Apr 2010)
New Revision: 2492

Added:
   portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/
   portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java
   portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java
   portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java
   portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
   portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java
   portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java
Modified:
   portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java
   portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java
Log:
JBEPP-265: GTNPORTAL-945 ported to the branch

Added: portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class Entry<V> implements Serializable
+{
+
+   public static <V> Entry<V> create(V v)
+   {
+      return new Entry<V>(v);
+   }
+
+   /** . */
+   private final V value;
+
+   private Entry(V value)
+   {
+      if (value == null)
+      {
+         throw new NullPointerException();
+      }
+      this.value = value;
+   }
+
+   public V getValue()
+   {
+      return value;
+   }
+
+   @Override
+   public String toString()
+   {
+      return "Entry[" + value + "]";
+   }
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+
+import java.util.concurrent.*;
+
+/**
+ * A future cache that prevents the loading of the same resource twice. This should be used when the resource
+ * to load is very expensive or cannot be concurrently retrieved (like a classloading). 
+ *
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class FutureCache<K, V, C>
+{
+
+   /** . */
+   private final Loader<K, V, C> loader;
+
+   /** . */
+   private final ConcurrentMap<K, FutureTask<Entry<V>>> local;
+
+   /** . */
+   private final Logger log = LoggerFactory.getLogger(FutureCache.class);
+
+   public FutureCache(Loader<K, V, C> loader)
+   {
+      this.loader = loader;
+      this.local = new ConcurrentHashMap<K, FutureTask<Entry<V>>>();
+   }
+
+   protected abstract Entry<V> get(K key);
+
+   protected abstract void put(K key, Entry<V> entry);
+
+   public V get(final C context, final K key)
+   {
+      // First we try a simple cache get
+      Entry<V> entry = get(key);
+
+      // If it does not succeed then we go through a process that will avoid to load
+      // the same resource concurrently
+      if (entry == null)
+      {
+         // Create our future
+         FutureTask<Entry<V>> future = new FutureTask<Entry<V>>(new Callable<Entry<V>>()
+         {
+            public Entry<V> call() throws Exception
+            {
+               // Retrieve the value from the loader
+               V value = loader.retrieve(context, key);
+
+               //
+               if (value != null)
+               {
+                  // Create the entry
+                  Entry<V> entry = Entry.create(value);
+
+                  // Cache it, it is made available to other threads (unless someone removes it)
+                  put(key, entry);
+
+                  // Return entry
+                  return entry;
+               }
+               else
+               {
+                  return null;
+               }
+            }
+         });
+
+         // Was our means that we inserted in the local
+         boolean inserted = true;
+
+         //
+         try
+         {
+            FutureTask<Entry<V>> phantom = local.putIfAbsent(key, future);
+
+            // Use the entry that could have been inserted by another thread
+            if (phantom != null)
+            {
+               future = phantom;
+               inserted = false;
+            }
+            else
+            {
+               future.run();
+            }
+
+            // Returns the entry
+            entry = future.get();
+         }
+         catch (ExecutionException e)
+         {
+            log.error("Computing of resource " + key + " threw an exception", e.getCause());
+         }
+         catch (Exception e)
+         {
+            log.error("Retrieval of resource " + key + " threw an exception", e);
+         }
+         finally
+         {
+            // Clean up the per key map but only if our insertion succeeded and with our future
+            if (inserted)
+            {
+               local.remove(key, future);
+            }
+         }
+      }
+
+      //
+      return entry != null ? entry.getValue() : null;
+   }
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import org.exoplatform.services.cache.ExoCache;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class FutureExoCache<K extends Serializable, V, C> extends FutureCache<K, V, C>
+{
+
+   /** . */
+   private final ExoCache<K, Entry<V>> cache;
+
+   public FutureExoCache(Loader<K, V, C> loader, ExoCache<K, Entry<V>> cache)
+   {
+      super(loader);
+
+      //
+      this.cache = cache;
+   }
+
+   @Override
+   protected Entry<V> get(K key)
+   {
+      return cache.get(key);
+   }
+
+   @Override
+   protected void put(K key, Entry<V> entry)
+   {
+      cache.put(key, entry);
+   }
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public interface Loader<K, V, C>
+{
+
+   V retrieve(C context, K key) throws Exception;
+
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.exoplatform.commons.cache.future.Entry;
+import org.exoplatform.commons.cache.future.FutureCache;
+import org.gatein.common.util.Tools;
+
+import java.util.*;
+import java.util.concurrent.Callable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ConcurrentGetWhenPutTestCase extends TestCase
+{
+
+   /** . */
+   private AssertionFailedError failure;
+
+   /** . */
+   private LinkedList<String> events = new LinkedList<String>();
+
+   FutureCache<String, String, Callable<String>> futureCache = new FutureCache<String, String, Callable<String>>(new StringLoader()) {
+
+
+      @Override
+      protected Entry<String> get(String key)
+      {
+         if (key == key1)
+         {
+            if (Thread.currentThread() != thread1)
+            {
+               failure = new AssertionFailedError();
+            }
+            events.addLast("get/key1");
+         }
+         else if (key == key2)
+         {
+            if (Thread.currentThread() != thread2)
+            {
+               failure = new AssertionFailedError();
+            }
+            events.addLast("get/key2");
+         }
+         else
+         {
+            failure = new AssertionFailedError();
+         }
+         return null;
+      }
+
+      @Override
+      protected void put(String key, Entry<String> entry)
+      {
+         if (key == key1)
+         {
+            if (Thread.currentThread() == thread1)
+            {
+               events.addLast("begin_put/key1/" + entry);
+
+               //
+               thread2.start();
+
+               //
+               while (thread2.getState() != Thread.State.WAITING)
+               {
+                  // Wait until thread 2 is blocked
+               }
+
+               //
+               events.addLast("end_put/key1");
+            }
+            else
+            {
+               failure = new AssertionFailedError();
+            }
+         }
+         else
+         {
+            failure = new AssertionFailedError();
+         }
+      }
+   };
+
+   /** . */
+   private final String key1 = new String("foo");
+
+   /** . */
+   private final String key2 = new String("foo");
+
+   Thread thread1 = new Thread()
+   {
+      @Override
+      public void run()
+      {
+         String v = futureCache.get(new Callable<String>()
+         {
+            public String call() throws Exception
+            {
+               events.addLast("call/key1");
+               return "foo_value_1";
+            }
+         }, key1);
+         events.addLast("retrieved/key1/" + v);
+      }
+   };
+
+   Thread thread2 = new Thread()
+   {
+      @Override
+      public void run()
+      {
+         String v = futureCache.get(new Callable<String>()
+         {
+            public String call() throws Exception
+            {
+               failure = new AssertionFailedError();
+               return "foo_value_2";
+            }
+         }, key2);
+         events.addLast("retrieved/key2/" + v);
+      }
+   };
+
+   public void testMain() throws Exception
+   {
+      thread1.start();
+
+      //
+      thread1.join();
+      thread2.join();
+
+      //
+      if (failure != null)
+      {
+         throw failure;
+      }
+
+      //
+      List<String> expectedEvents = Arrays.asList(
+         "get/key1",
+         "call/key1",
+         "begin_put/key1/Entry[foo_value_1]",
+         "get/key2",
+         "end_put/key1"
+      );
+
+      //
+      assertEquals(expectedEvents, events.subList(0, expectedEvents.size()));
+
+      //
+      Set<String> expectedEndEvents = Tools.toSet("retrieved/key1/foo_value_1", "retrieved/key2/foo_value_1");
+      assertEquals(expectedEndEvents, new HashSet<String>(events.subList(expectedEvents.size(), events.size())));
+   }
+
+}
\ No newline at end of file

Added: portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import org.exoplatform.commons.cache.future.Entry;
+import org.exoplatform.commons.cache.future.FutureCache;
+import org.exoplatform.commons.cache.future.Loader;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class FutureMap<C> extends FutureCache<String, String, C>
+{
+
+   /** . */
+   final Map<String, Entry<String>> data;
+
+   public FutureMap(Loader<String, String, C> loader)
+   {
+      super(loader);
+
+      //
+      this.data = Collections.synchronizedMap(new HashMap<String, Entry<String>>());
+   }
+
+   @Override
+   protected Entry<String> get(String key)
+   {
+      return data.get(key);
+   }
+
+   @Override
+   protected void put(String key, Entry<String> entry)
+   {
+      data.put(key, entry);
+   }
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class GetTestCase extends TestCase
+{
+   public void testGet()
+   {
+      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      Assert.assertEquals("foo_value", futureCache.get(new Callable<String>()
+      {
+         public String call() throws Exception
+         {
+            return "foo_value";
+         }
+      }, "foo"));
+      Assert.assertEquals("foo_value", futureCache.data.get("foo").getValue());
+   }
+
+   public void testNullValue()
+   {
+      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      Assert.assertEquals(null, futureCache.get(new Callable<String>()
+      {
+         public String call() throws Exception
+         {
+            return null;
+         }
+      }, "foo"));
+      Assert.assertFalse(futureCache.data.containsKey("foo"));
+   }
+
+   public void testThrowException()
+   {
+      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      Assert.assertEquals(null, futureCache.get(new Callable<String>()
+      {
+         public String call() throws Exception
+         {
+            throw new Exception("DON'T FREAK OUT");
+         }
+      }, "foo"));
+      Assert.assertFalse(futureCache.data.containsKey("foo"));
+   }
+}

Added: portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import org.exoplatform.commons.cache.future.Loader;
+
+import java.util.concurrent.Callable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class StringLoader implements Loader<String, String, Callable<String>>
+{
+   public String retrieve(Callable<String> context, String key) throws Exception
+   {
+      return context.call();
+   }
+}

Modified: portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java	2010-04-06 13:11:04 UTC (rev 2491)
+++ portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -22,8 +22,11 @@
 import groovy.lang.Writable;
 import groovy.text.Template;
 
+import org.exoplatform.commons.cache.future.Entry;
+import org.exoplatform.commons.cache.future.FutureCache;
+import org.exoplatform.commons.cache.future.FutureExoCache;
+import org.exoplatform.commons.cache.future.Loader;
 import org.exoplatform.commons.utils.IOUtil;
-import org.exoplatform.container.xml.InitParams;
 import org.exoplatform.groovyscript.GroovyTemplate;
 import org.exoplatform.groovyscript.GroovyTemplateEngine;
 import org.exoplatform.management.annotations.Impact;
@@ -34,9 +37,11 @@
 import org.exoplatform.management.jmx.annotations.NameTemplate;
 import org.exoplatform.management.jmx.annotations.Property;
 import org.exoplatform.management.rest.annotations.RESTEndpoint;
+import org.exoplatform.resolver.ResourceKey;
 import org.exoplatform.resolver.ResourceResolver;
 import org.exoplatform.services.cache.CacheService;
 import org.exoplatform.services.cache.ExoCache;
+import org.gatein.common.io.IOTools;
 
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -54,17 +59,52 @@
 
    private GroovyTemplateEngine engine_;
 
-   private ExoCache<String, GroovyTemplate> templatesCache_;
+   private ExoCache<ResourceKey, Entry<GroovyTemplate>> templatesCache_;
 
    private TemplateStatisticService statisticService;
 
    private boolean cacheTemplate_ = true;
 
+   private final Loader<ResourceKey, GroovyTemplate, ResourceResolver> loader = new Loader<ResourceKey, GroovyTemplate, ResourceResolver>()
+   {
+      public GroovyTemplate retrieve(ResourceResolver context, ResourceKey key) throws Exception
+      {
+         byte[] bytes;
+         InputStream is = context.getInputStream(key.getURL());
+         try
+         {
+            bytes = IOUtil.getStreamContentAsBytes(is);
+            is.close();
+         }
+         finally
+         {
+            IOTools.safeClose(is);
+         }
+
+         // The template class name
+         int pos = key.getURL().lastIndexOf('/');
+         if (pos == -1)
+         {
+            pos = 0;
+         }
+         String name = key.getURL().substring(pos);
+
+         // Julien: it's a bit dangerious here, with respect to the file encoding...
+         String text = new String(bytes);
+
+         // Finally do the expensive template creation
+         return engine_.createTemplate(key.getURL(), name, text);
+      }
+   };
+
+   private FutureCache<ResourceKey, GroovyTemplate, ResourceResolver> futureCache;
+
    public TemplateService(TemplateStatisticService statisticService, CacheService cservice) throws Exception
    {
       this.engine_ = new GroovyTemplateEngine();
       this.statisticService = statisticService;
       this.templatesCache_ = cservice.getCacheInstance(TemplateService.class.getSimpleName());
+      this.futureCache = new FutureExoCache<ResourceKey, GroovyTemplate, ResourceResolver>(loader, templatesCache_);
    }
 
    public void merge(String name, BindingContext context) throws Exception
@@ -108,37 +148,18 @@
 
    final public GroovyTemplate getTemplate(String url, ResourceResolver resolver, boolean cacheable) throws Exception
    {
-      GroovyTemplate template = null;
+      GroovyTemplate template;
+      ResourceKey resourceId = resolver.createResourceKey(url);
       if (cacheable)
       {
-         String resourceId = resolver.createResourceId(url);
-         template = getTemplatesCache().get(resourceId);
+         template = futureCache.get(resolver, resourceId);
       }
-      if (template != null)
-         return template;
-      InputStream is;
-      byte[] bytes = null;
-      is = resolver.getInputStream(url);
-      bytes = IOUtil.getStreamContentAsBytes(is);
-      is.close();
-
-      // The template class name
-      int pos = url.lastIndexOf('/');
-      if (pos == -1)
+      else
       {
-         pos = 0;
+         template = loader.retrieve(resolver, resourceId);
       }
-      String name = url.substring(pos);
 
-      String text = new String(bytes);
-      template = engine_.createTemplate(url, name, text);
-
-      if (cacheable)
-      {
-         String resourceId = resolver.createResourceId(url);
-         getTemplatesCache().put(resourceId, template);
-      }
-
+      //
       return template;
    }
 
@@ -148,7 +169,7 @@
       getTemplatesCache().remove(resourceId);
    }
 
-   public ExoCache<String, GroovyTemplate> getTemplatesCache()
+   public ExoCache<ResourceKey, Entry<GroovyTemplate>> getTemplatesCache()
    {
       return templatesCache_;
    }
@@ -198,9 +219,13 @@
       try
       {
          ArrayList<String> list = new ArrayList<String>();
-         for (GroovyTemplate template : templatesCache_.getCachedObjects())
+         for (Entry<GroovyTemplate> entry : templatesCache_.getCachedObjects())
          {
-            list.add(template.getId());
+            GroovyTemplate template = entry.getValue();
+            if (template != null)
+            {
+               list.add(template.getId());
+            }
          }
          return list.toArray(new String[list.size()]);
       }

Added: portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java	                        (rev 0)
+++ portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.resolver;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ResourceKey implements Serializable
+{
+
+   /** . */
+   private final int resolverId;
+
+   /** . */
+   private final String url;
+
+   public ResourceKey(int resolverId, String url)
+   {
+      if (url == null)
+      {
+         throw new NullPointerException("no null URL accepted");
+      }
+      this.resolverId = resolverId;
+      this.url = url;
+   }
+
+   public String getURL()
+   {
+      return url;
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return resolverId ^ url.hashCode();
+   }
+
+   @Override
+   public boolean equals(Object o)
+   {
+      if (o == this)
+      {
+         return true;
+      }
+      if (o instanceof ResourceKey)
+      {
+         ResourceKey that = (ResourceKey)o;
+         return resolverId == that.resolverId && url.equals(that.url);
+      }
+      return false;
+   }
+}

Modified: portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java
===================================================================
--- portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java	2010-04-06 13:11:04 UTC (rev 2491)
+++ portal/branches/EPP_5_0_Branch/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java	2010-04-06 13:32:13 UTC (rev 2492)
@@ -54,6 +54,11 @@
       throw new RuntimeException("unsupported method");
    }
 
+   public ResourceKey createResourceKey(String url)
+   {
+      return new ResourceKey(hashCode(), url);
+   }
+
    public String createResourceId(String url)
    {
       return hashCode() + ":" + url;



More information about the gatein-commits mailing list