Author: hoang_to
Date: 2011-07-21 06:11:31 -0400 (Thu, 21 Jul 2011)
New Revision: 6904
Added:
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/test/java/org/exoplatform/application/registry/TestApplicationRegistryServiceCache.java
Modified:
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/main/java/org/exoplatform/application/registry/impl/ApplicationRegistryServiceImpl.java
Log:
GTNPORTAL-1959: Missing cache of categories in ApplicationRegistryService
Modified:
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/main/java/org/exoplatform/application/registry/impl/ApplicationRegistryServiceImpl.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/main/java/org/exoplatform/application/registry/impl/ApplicationRegistryServiceImpl.java 2011-07-21
10:05:51 UTC (rev 6903)
+++
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/main/java/org/exoplatform/application/registry/impl/ApplicationRegistryServiceImpl.java 2011-07-21
10:11:31 UTC (rev 6904)
@@ -52,6 +52,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
/**
* The fundamental reason that motives to use tasks is because of the JMX access that
does not setup a context and
@@ -85,6 +86,8 @@
/** . */
final POMSessionManager mopManager;
+ private final AtomicReference<List<ApplicationCategory>> allCategories;
+
/** Should match WSRPPortletInfo.PRODUCER_NAME_META_INFO_KEY */
private static final String PRODUCER_NAME_META_INFO_KEY = "producer-name";
public static final String PRODUCER_CATEGORY_NAME_SUFFIX = " Producer";
@@ -98,6 +101,8 @@
this.manager = manager;
this.lifeCycle = lifeCycle;
this.mopManager = mopManager;
+
+ this.allCategories = new AtomicReference<List<ApplicationCategory>>();
}
public ContentRegistry getContentRegistry()
@@ -128,6 +133,11 @@
String accessUser,
final ApplicationType<?>... appTypes) throws Exception
{
+ if(appTypes == null || appTypes.length == 0)
+ {
+ return getAllApplicationCategories(sortComparator);
+ }
+
final List<ApplicationCategory> categories = new
ArrayList<ApplicationCategory>();
//
@@ -150,6 +160,38 @@
return categories;
}
+ private List<ApplicationCategory>
getAllApplicationCategories(Comparator<ApplicationCategory> comparator) throws
Exception
+ {
+ if(allCategories.get() == null)
+ {
+ List<ApplicationCategory> categories = new
ArrayList<ApplicationCategory>();
+ ContentRegistry registry = getContentRegistry();
+
+ for(CategoryDefinition categoryDef : registry.getCategoryList())
+ {
+ ApplicationCategory category = new ApplicationCategory();
+
+ category.setName(categoryDef.getName());
+ category.setDisplayName(categoryDef.getDisplayName());
+ category.setDescription(categoryDef.getDescription());
+ category.setAccessPermissions(categoryDef.getAccessPermissions());
+ category.setCreatedDate(categoryDef.getCreationDate());
+ category.setModifiedDate(categoryDef.getLastModificationDate());
+
+ for(ContentDefinition contentDef : categoryDef.getContentList())
+ {
+ category.getApplications().add(load(contentDef));
+ }
+
+ categories.add(category);
+ }
+
+ allCategories.compareAndSet(null, categories);
+ }
+
+ return allCategories.get();
+ }
+
public List<ApplicationCategory> getApplicationCategories(String accessUser,
ApplicationType<?>... appTypes) throws Exception
{
return getApplicationCategories(null, accessUser, appTypes);
@@ -183,6 +225,8 @@
public void save(final ApplicationCategory category) throws Exception
{
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
//
@@ -205,6 +249,8 @@
public void remove(final ApplicationCategory category) throws Exception
{
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
registry.getCategoryMap().remove(category.getName());
}
@@ -287,6 +333,8 @@
public void save(final ApplicationCategory category, final Application application)
throws Exception
{
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
//
@@ -325,6 +373,9 @@
public void update(final Application application) throws Exception
{
+ //Invalidate the categories cache
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
//
@@ -348,6 +399,9 @@
public void remove(final Application app) throws Exception
{
+ //Invalidate the categories cache
+ allCategories.set(null);
+
if (app == null)
{
throw new NullPointerException();
@@ -371,6 +425,9 @@
public void importExoGadgets() throws Exception
{
+ //Invalidate the categories cache
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
//
@@ -412,6 +469,9 @@
public void importAllPortlets() throws Exception
{
+ //Invalidate the categories cache
+ allCategories.set(null);
+
ContentRegistry registry = getContentRegistry();
//
Added:
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/test/java/org/exoplatform/application/registry/TestApplicationRegistryServiceCache.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/test/java/org/exoplatform/application/registry/TestApplicationRegistryServiceCache.java
(rev 0)
+++
portal/branches/branch-GTNPORTAL-1963/component/application-registry/src/test/java/org/exoplatform/application/registry/TestApplicationRegistryServiceCache.java 2011-07-21
10:11:31 UTC (rev 6904)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011 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.application.registry;
+
+import org.exoplatform.application.AbstractApplicationRegistryTest;
+import org.exoplatform.commons.chromattic.ChromatticManager;
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.container.component.RequestLifeCycle;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * For the moment, we cache only list of all categories in ApplicationRegistryService.
Hence, this test suite
+ * handles only ApplicationCategory entities
+ *
+ * @author <a href="hoang281283(a)gmail.com">Minh Hoang TO</a>
+ * @date 7/21/11
+ */
+public class TestApplicationRegistryServiceCache extends AbstractApplicationRegistryTest
+{
+
+ private PortalContainer portalContainer;
+
+ private ChromatticManager cManager;
+
+ private ApplicationRegistryService appResService;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ portalContainer = getContainer();
+ cManager =
(ChromatticManager)portalContainer.getComponentInstanceOfType(ChromatticManager.class);
+ appResService =
(ApplicationRegistryService)portalContainer.getComponentInstanceOfType(ApplicationRegistryService.class);
+ begin();
+ }
+
+ public void testConcurrentReadAndWrite() throws Exception
+ {
+ //As current test suite is inteferenced by TestApplicationRegistryService
testsuite, we could not
+ //give an explicit number of existing categories
+ final int numberOfCategories = appResService.getApplicationCategories().size();
+
+ final CountDownLatch latch = new CountDownLatch(5);
+ for (int i = 0; i < 5; i++)
+ {
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ RequestLifeCycle.begin(portalContainer);
+ List<ApplicationCategory> categories =
appResService.getApplicationCategories();
+ assertEquals(numberOfCategories, categories.size());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ //Synchronize ChromatticSession with JCR Session in this thread
+ cManager.getSynchronization().setSaveOnClose(true);
+ RequestLifeCycle.end();
+ latch.countDown();
+ }
+ }
+ }).start();
+ }
+
+ final CountDownLatch finishWriteTask = new CountDownLatch(1);
+ Thread writeTask = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ latch.await();
+
+ RequestLifeCycle.begin(portalContainer);
+ ApplicationCategory category = new ApplicationCategory();
+ category.setName("ABC");
+ category.setDisplayName("ABC");
+ category.setDescription("ABC");
+
+ appResService.save(category);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ cManager.getSynchronization().setSaveOnClose(true);
+ RequestLifeCycle.end();
+ finishWriteTask.countDown();
+ }
+ }
+ });
+
+ writeTask.start();
+
+ //REMARK: We could not check the update from main thread as the ChromatticSession
associated with current thread
+ //had been openned before the writeTask thread terminates its execution
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ finishWriteTask.await();
+
+ RequestLifeCycle.begin(portalContainer);
+ List<ApplicationCategory> categories =
appResService.getApplicationCategories();
+
+ assertEquals(numberOfCategories + 1, categories.size());
+ ApplicationCategory abcCategory = null;
+ //We use this loop instead of direct query to check if the cache works
properly
+ for (ApplicationCategory category : categories)
+ {
+ if ("ABC".equals(category.getName()))
+ {
+ abcCategory = category;
+ break;
+ }
+ }
+ assertNotNull(abcCategory);
+ appResService.remove(abcCategory);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ cManager.getSynchronization().setSaveOnClose(true);
+ RequestLifeCycle.end();
+ }
+ }
+ }).start();
+
+ //Hack to overcome the delay problem, which leads to failure in other testsuites
+ try
+ {
+ Thread.sleep(3000);
+ }
+ catch(InterruptedException inEx)
+ {
+ inEx.printStackTrace();
+ }
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ //ChromatticSession is not synchronized with JCR Session in the main thread
+ cManager.getSynchronization().setSaveOnClose(false);
+ end();
+ }
+
+}