Author: julien_viet
Date: 2010-04-06 06:11:02 -0400 (Tue, 06 Apr 2010)
New Revision: 2487
Added:
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java
Modified:
portal/trunk/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java
Log:
GTNPORTAL-945 : Handle gracefully concurrent compilation of the same template
Added:
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java
===================================================================
---
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java
(rev 0)
+++
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Entry.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java
===================================================================
---
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java
(rev 0)
+++
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureCache.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java
===================================================================
---
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java
(rev 0)
+++
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureExoCache.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java
===================================================================
---
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java
(rev 0)
+++
portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/Loader.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public interface Loader<K, V, C>
+{
+
+ V retrieve(C context, K key) throws Exception;
+
+}
Added:
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java
===================================================================
---
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java
(rev 0)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/ConcurrentGetWhenPutTestCase.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
===================================================================
---
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
(rev 0)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
===================================================================
---
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
(rev 0)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java
===================================================================
---
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java
(rev 0)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/StringLoader.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java
===================================================================
---
portal/trunk/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java 2010-04-06
09:44:10 UTC (rev 2486)
+++
portal/trunk/component/scripting/src/main/java/org/exoplatform/groovyscript/text/TemplateService.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java
===================================================================
---
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java
(rev 0)
+++
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceKey.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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@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/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java
===================================================================
---
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java 2010-04-06
09:44:10 UTC (rev 2486)
+++
portal/trunk/component/scripting/src/main/java/org/exoplatform/resolver/ResourceResolver.java 2010-04-06
10:11:02 UTC (rev 2487)
@@ -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;