)AlfrescoTransactionSupport.getResource(KEY_DELETED_USER_IDS);
+ if (deletedUserIds != null)
+ {
+ for (String userId : deletedUserIds)
+ {
+ try
+ {
+ // Since we are in post-commit, we do best-effort
+ feedDAO.deleteUserFeedEntries(userId);
+ }
+ catch (SQLException e)
+ {
+ logger.error("Activities feed cleanup for user '"+userId+"' failed: ", e);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java
index 8c8ce6236d..0cd58c68fe 100644
--- a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java
+++ b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java
@@ -24,13 +24,16 @@ import java.util.Date;
import junit.framework.TestCase;
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.activities.ActivityFeedDAO;
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.PropertyMap;
import org.springframework.context.ApplicationContext;
/**
@@ -45,12 +48,31 @@ public class FeedCleanerTest extends TestCase
private ActivityFeedDAO feedDAO;
private FeedCleaner cleaner;
private SiteService siteService;
+ private PersonService personService;
protected RetryingTransactionHelper transactionHelper;
+ private static final String TEST_SITE = "testSite";
+
+ private static final String TEST_SITE_1 = TEST_SITE+"1";
+ private static final String TEST_SITE_2 = TEST_SITE+"2";
+ private static final String TEST_SITE_3 = TEST_SITE+"3";
+ private static final String TEST_SITE_4 = TEST_SITE+"4";
+ private static final String TEST_SITE_5 = TEST_SITE+"5";
+ private static final String TEST_SITE_6 = TEST_SITE+"6";
+ private static final String TEST_SITE_7 = TEST_SITE+"7";
+
+ private static final String TEST_USER_A = "testUserA";
+ private static final String TEST_USER_B = "testUserB";
+ private static final String TEST_USER_C = "testUserC";
+ private static final String TEST_USER_D = "testUserD";
+ private static final String TEST_USER_E = "testUserE";
+ private static final String TEST_USER_F = "testUserF";
+
@Override
public void setUp() throws Exception
{
siteService = (SiteService) ctx.getBean("SiteService");
+ personService = (PersonService) ctx.getBean("PersonService");
feedDAO = (ActivityFeedDAO) ctx.getBean("feedDAO");
transactionHelper = (RetryingTransactionHelper)ctx.getBean("retryingTransactionHelper");
@@ -96,15 +118,15 @@ public class FeedCleanerTest extends TestCase
{
cleaner.setMaxFeedSize(0);
- // insert site feed entries for "testSite1"
+ // insert site feed entries for TEST_SITE_1
ActivityFeedEntity feedEntry = new ActivityFeedEntity();
feedEntry.setPostDate(new Date(System.currentTimeMillis()-(20*60*1000L))); // 20 mins ago
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite1");
+ feedEntry.setSiteNetwork(TEST_SITE_1);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
+ feedEntry.setPostUserId(TEST_USER_A);
feedEntry.setFeedUserId("");
feedEntry.setFeedDate(new Date());
@@ -114,13 +136,13 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date()); // now
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite1");
+ feedEntry.setSiteNetwork(TEST_SITE_1);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
+ feedEntry.setPostUserId(TEST_USER_A);
feedEntry.setFeedUserId("");
feedEntry.setFeedDate(new Date());
- // insert user feed entries for "testUserB"
+ // insert user feed entries for TEST_USER_B
feedDAO.insertFeedEntry(feedEntry);
@@ -128,10 +150,10 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date(System.currentTimeMillis()-(20*60*1000L))); // 20 mins ago
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite2");
+ feedEntry.setSiteNetwork(TEST_SITE_2);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
- feedEntry.setFeedUserId("testUserB");
+ feedEntry.setPostUserId(TEST_USER_A);
+ feedEntry.setFeedUserId(TEST_USER_B);
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
@@ -140,30 +162,30 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date()); // now
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite3");
+ feedEntry.setSiteNetwork(TEST_SITE_3);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
- feedEntry.setFeedUserId("testUserB");
+ feedEntry.setPostUserId(TEST_USER_A);
+ feedEntry.setFeedUserId(TEST_USER_B);
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
- assertEquals(2, feedDAO.selectSiteFeedEntries("testSite1", "json").size());
- assertEquals(2, feedDAO.selectUserFeedEntries("testUserB", "json", null, false, false).size());
+ assertEquals(2, feedDAO.selectSiteFeedEntries(TEST_SITE_1, "json", -1).size());
+ assertEquals(2, feedDAO.selectUserFeedEntries(TEST_USER_B, "json", null, false, false, -1L, -1).size());
// fire the cleaner
cleaner.setMaxAgeMins(10);
cleaner.execute();
- assertEquals(1, feedDAO.selectSiteFeedEntries("testSite1", "json").size());
- assertEquals(1, feedDAO.selectUserFeedEntries("testUserB", "json", null, false, false).size());
+ assertEquals(1, feedDAO.selectSiteFeedEntries(TEST_SITE_1, "json", -1).size());
+ assertEquals(1, feedDAO.selectUserFeedEntries(TEST_USER_B, "json", null, false, false, -1L, -1).size());
}
public void testMaxSize() throws Exception
{
cleaner.setMaxAgeMins(0);
- // insert site feed entries for "testSite4"
+ // insert site feed entries for TEST_SITE_4
for (int i = 0; i < 10; i++)
{
@@ -171,16 +193,16 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite4");
+ feedEntry.setSiteNetwork(TEST_SITE_4);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserC");
+ feedEntry.setPostUserId(TEST_USER_C);
feedEntry.setFeedUserId("");
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
}
- // insert user feed entries for user "testUserD"
+ // insert user feed entries for user TEST_USER_D
for (int i = 0; i < 10; i++)
{
@@ -188,28 +210,28 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite5");
+ feedEntry.setSiteNetwork(TEST_SITE_5);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
- feedEntry.setFeedUserId("testUserD");
+ feedEntry.setPostUserId(TEST_USER_A);
+ feedEntry.setFeedUserId(TEST_USER_D);
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
}
- assertEquals(10, feedDAO.selectSiteFeedEntries("testSite4", "json").size());
- assertEquals(10, feedDAO.selectUserFeedEntries("testUserD", "json", null, false, false).size());
+ assertEquals(10, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ assertEquals(10, feedDAO.selectUserFeedEntries(TEST_USER_D, "json", null, false, false, -1L, -1).size());
// fire the cleaner
cleaner.setMaxFeedSize(2);
cleaner.execute();
- assertEquals(2, feedDAO.selectSiteFeedEntries("testSite4", "json").size());
- assertEquals(2, feedDAO.selectUserFeedEntries("testUserD", "json", null, false, false).size());
+ assertEquals(2, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ assertEquals(2, feedDAO.selectUserFeedEntries(TEST_USER_D, "json", null, false, false, -1L, -1).size());
Date sameTime = new Date();
- // insert site feed entries for "testSite6"
+ // insert site feed entries for TEST_SITE_6
for (int i = 0; i < 10; i++)
{
@@ -217,16 +239,16 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(sameTime);
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite6");
+ feedEntry.setSiteNetwork(TEST_SITE_6);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserE");
+ feedEntry.setPostUserId(TEST_USER_E);
feedEntry.setFeedUserId("");
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
}
- // insert user feed entries for user "testUserF"
+ // insert user feed entries for user TEST_USER_F
for (int i = 0; i < 10; i++)
{
@@ -234,17 +256,17 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(sameTime);
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite7");
+ feedEntry.setSiteNetwork(TEST_SITE_7);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserA");
- feedEntry.setFeedUserId("testUserF");
+ feedEntry.setPostUserId(TEST_USER_A);
+ feedEntry.setFeedUserId(TEST_USER_F);
feedEntry.setFeedDate(new Date());
feedDAO.insertFeedEntry(feedEntry);
}
- assertEquals(10, feedDAO.selectSiteFeedEntries("testSite6", "json").size());
- assertEquals(10, feedDAO.selectUserFeedEntries("testUserF", "json", null, false, false).size());
+ assertEquals(10, feedDAO.selectSiteFeedEntries(TEST_SITE_6, "json", -1).size());
+ assertEquals(10, feedDAO.selectUserFeedEntries(TEST_USER_F, "json", null, false, false, -1L, -1).size());
// fire the cleaner
cleaner.setMaxFeedSize(2);
@@ -252,8 +274,162 @@ public class FeedCleanerTest extends TestCase
// note: no effect, since entries at max feed size have same time (eg. to nearest minute)
- assertEquals(10, feedDAO.selectSiteFeedEntries("testSite6", "json").size());
- assertEquals(10, feedDAO.selectUserFeedEntries("testUserF", "json", null, false, false).size());
+ assertEquals(10, feedDAO.selectSiteFeedEntries(TEST_SITE_6, "json", -1).size());
+ assertEquals(10, feedDAO.selectUserFeedEntries(TEST_USER_F, "json", null, false, false, -1L, -1).size());
+ }
+
+ public void testSiteDelete() throws Exception
+ {
+ cleaner.setMaxAgeMins(100);
+
+ assertEquals(0, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ assertEquals(0, feedDAO.selectUserFeedEntries(TEST_USER_D, "json", null, false, false, -1L, -1).size());
+
+ int site4FeedCnt = 10;
+
+ // insert site / user feed entries (for TEST_SITE_4 and TEST_USER_D)
+ for (int i = 0; i < site4FeedCnt; i++)
+ {
+ ActivityFeedEntity feedEntry = new ActivityFeedEntity();
+
+ feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
+ feedEntry.setActivitySummaryFormat("json");
+ feedEntry.setSiteNetwork(TEST_SITE_4);
+ feedEntry.setActivityType("testActivityType");
+ feedEntry.setPostUserId(TEST_USER_C);
+ feedEntry.setFeedUserId("");
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry); // for TEST_SITE_4 site feed
+
+ feedEntry.setFeedUserId(TEST_USER_D); // for TEST_USER_D user feed
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry);
+ }
+
+ int site5FeedCnt = 5;
+
+ // add some additional user feed entries (for TEST_SITE_5 and TEST_USER_D)
+ for (int i = 0; i < site5FeedCnt; i++)
+ {
+ ActivityFeedEntity feedEntry = new ActivityFeedEntity();
+
+ feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
+ feedEntry.setActivitySummaryFormat("json");
+ feedEntry.setSiteNetwork(TEST_SITE_5);
+ feedEntry.setActivityType("testActivityType");
+ feedEntry.setPostUserId(TEST_USER_C);
+ feedEntry.setFeedUserId(TEST_USER_D);
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry);
+ }
+
+ assertEquals(site4FeedCnt, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ assertEquals(site4FeedCnt+site5FeedCnt, feedDAO.selectUserFeedEntries(TEST_USER_D, "json", null, false, false,-1L, -1).size());
+
+ // delete the site
+ siteService.deleteSite(TEST_SITE_4);
+
+ assertEquals(0, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ assertEquals(site5FeedCnt, feedDAO.selectUserFeedEntries(TEST_USER_D, "json", null, false, false, -1L, -1).size());
+
+ siteService.createSite("mypreset", TEST_SITE_4, TEST_SITE_4, TEST_SITE_4, SiteVisibility.PUBLIC);
+
+ assertEquals(0, feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size());
+ }
+
+ public void testPersonDelete() throws Exception
+ {
+ cleaner.setMaxAgeMins(100);
+
+ createPerson(TEST_USER_E); // ignore result
+
+ assertEquals(0, feedDAO.selectSiteFeedEntries(TEST_SITE_6, "json", -1).size());
+ assertEquals(0, feedDAO.selectUserFeedEntries(TEST_USER_E, "json", null, false, false, -1L, -1).size());
+
+ int site6FeedCnt = 10;
+
+ // insert site / user feed entries (for TEST_SITE_6 and TEST_USER_E)
+ for (int i = 0; i < site6FeedCnt; i++)
+ {
+ ActivityFeedEntity feedEntry = new ActivityFeedEntity();
+
+ feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
+ feedEntry.setActivitySummaryFormat("json");
+ feedEntry.setSiteNetwork(TEST_SITE_6);
+ feedEntry.setActivityType("testActivityType");
+ feedEntry.setPostUserId(TEST_USER_E);
+ feedEntry.setFeedUserId("");
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry); // for TEST_SITE_6 site feed
+
+ feedEntry.setFeedUserId(TEST_USER_E); // for TEST_USER_E user feed
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry);
+ }
+
+ int site7FeedCnt = 5;
+
+ // insert site / user feed entries (for TEST_SITE_7 and TEST_USER_E)
+ for (int i = 0; i < site7FeedCnt; i++)
+ {
+ ActivityFeedEntity feedEntry = new ActivityFeedEntity();
+
+ feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
+ feedEntry.setActivitySummaryFormat("json");
+ feedEntry.setSiteNetwork(TEST_SITE_7);
+ feedEntry.setActivityType("testActivityType");
+ feedEntry.setPostUserId(TEST_USER_E);
+ feedEntry.setFeedUserId("");
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry); // for TEST_SITE_7 site feed
+
+ feedEntry.setFeedUserId(TEST_USER_E); // for TEST_USER_E user feed
+ feedEntry.setFeedDate(new Date());
+
+ feedDAO.insertFeedEntry(feedEntry);
+ }
+
+ assertEquals(site6FeedCnt, feedDAO.selectSiteFeedEntries(TEST_SITE_6, "json", -1).size());
+ assertEquals(site7FeedCnt, feedDAO.selectSiteFeedEntries(TEST_SITE_7, "json", -1).size());
+ assertEquals(site6FeedCnt+site7FeedCnt, feedDAO.selectUserFeedEntries(TEST_USER_E, "json", null, false, false, -1L, -1).size());
+
+ // delete the person
+ personService.deletePerson(TEST_USER_E);
+
+ assertEquals(site6FeedCnt, feedDAO.selectSiteFeedEntries(TEST_SITE_6, "json", -1).size());
+ assertEquals(site7FeedCnt, feedDAO.selectSiteFeedEntries(TEST_SITE_7, "json", -1).size());
+
+ assertEquals(0, feedDAO.selectUserFeedEntries(TEST_USER_E, "json", null, false, false, -1L, -1).size());
+
+ assertTrue(createPerson(TEST_USER_E));
+
+ assertEquals(0, feedDAO.selectUserFeedEntries(TEST_USER_E, "json", null, false, false, -1L, -1).size());
+ }
+
+ private boolean createPerson(String userName)
+ {
+ if (this.personService.personExists(userName) == false)
+ {
+ // create person properties
+ PropertyMap personProps = new PropertyMap();
+ personProps.put(ContentModel.PROP_USERNAME, userName);
+ personProps.put(ContentModel.PROP_FIRSTNAME, userName);
+ personProps.put(ContentModel.PROP_LASTNAME, userName);
+ personProps.put(ContentModel.PROP_EMAIL, userName+"@email.com");
+
+ // create person node for user
+ this.personService.createPerson(personProps);
+
+ return true;
+ }
+
+ return false; // already exists
}
public void testConcurrentAccessAndRemoval() throws Exception
@@ -322,9 +498,9 @@ public class FeedCleanerTest extends TestCase
feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L)));
feedEntry.setActivitySummaryFormat("json");
- feedEntry.setSiteNetwork("testSite4");
+ feedEntry.setSiteNetwork(TEST_SITE_4);
feedEntry.setActivityType("testActivityType");
- feedEntry.setPostUserId("testUserC");
+ feedEntry.setPostUserId(TEST_USER_C);
feedEntry.setFeedUserId("");
feedEntry.setFeedDate(new Date());
@@ -350,7 +526,7 @@ public class FeedCleanerTest extends TestCase
public Integer execute() throws Throwable
{
// query some entries
- int selectCount = feedDAO.selectSiteFeedEntries("testSite4", "json").size();
+ int selectCount = feedDAO.selectSiteFeedEntries(TEST_SITE_4, "json", -1).size();
return selectCount;
}
});
@@ -385,4 +561,4 @@ public class FeedCleanerTest extends TestCase
}
}
}
-}
\ No newline at end of file
+}
diff --git a/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java b/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java
index aa7888ce43..77869aa073 100644
--- a/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java
+++ b/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java
@@ -139,7 +139,10 @@ public class PostLookup
if (activityPosts.size() > 0)
{
- logger.info("Update: " + activityPosts.size() + " activity posts");
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Update: " + activityPosts.size() + " activity post"+(activityPosts.size() == 1 ? "s" : ""));
+ }
}
for (final ActivityPostEntity activityPost : activityPosts)
diff --git a/source/java/org/alfresco/repo/admin/RepoAdminService.java b/source/java/org/alfresco/repo/admin/RepoAdminService.java
deleted file mode 100644
index cbe3ed1a25..0000000000
--- a/source/java/org/alfresco/repo/admin/RepoAdminService.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
- *
- * This file is part of Alfresco
- *
- * Alfresco 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 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco 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 Alfresco. If not, see .
- */
-package org.alfresco.repo.admin;
-
-import java.io.InputStream;
-import java.util.List;
-
-import org.alfresco.service.Auditable;
-import org.alfresco.service.namespace.QName;
-
-
-/**
- * Repository Admin Service interface.
- *
- * This interface provides certain repository administrative methods to:
- *
- * - deploy/undeploy custom content models to/from repository
- * - deploy/undeploy custom messages resources to/from repository
- *
- * Initially, this will support models and messages used by workflow process definitions.
- */
-
-public interface RepoAdminService
-{
- /* Custom models managed in the repository */
-
- public List getModels();
-
- public void deployModel(InputStream modelStream, String modelFileName);
-
- public QName undeployModel(String modelFileName);
-
- public QName activateModel(String modelFileName);
-
- public QName deactivateModel(String modelFileName);
-
- /* Custom message/resource bundles managed in the repository */
-
- public List getMessageBundles();
-
- public String deployMessageBundle(String resourceClasspath);
-
- public void undeployMessageBundle(String bundleBaseName);
-
- public void reloadMessageBundle(String bundleBaseName);
-
-}
diff --git a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java
index c365af6f85..8578fffab0 100644
--- a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java
+++ b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java
@@ -35,7 +35,11 @@ import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.repo.dictionary.RepositoryLocation;
import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.i18n.MessageServiceImpl;
+import org.alfresco.repo.usage.RepoUsageComponent;
import org.alfresco.service.cmr.admin.RepoAdminService;
+import org.alfresco.service.cmr.admin.RepoUsage;
+import org.alfresco.service.cmr.admin.RepoUsage.UsageType;
+import org.alfresco.service.cmr.admin.RepoUsageStatus;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -61,13 +65,11 @@ import org.springframework.extensions.surf.util.ParameterCheck;
* Repository Admin Service Implementation.
*
* @see RepoAdminService interface
- *
*/
-
public class RepoAdminServiceImpl implements RepoAdminService
{
// Logging support
- private static Log logger = LogFactory.getLog("org.alfresco.repo.admin.RepoAdminServiceImpl");
+ private static Log logger = LogFactory.getLog(RepoAdminServiceImpl.class);
// dependencies
private DictionaryDAO dictionaryDAO;
@@ -76,6 +78,7 @@ public class RepoAdminServiceImpl implements RepoAdminService
private ContentService contentService;
private NamespaceService namespaceService;
private MessageService messageService;
+ private RepoUsageComponent repoUsageComponent;
private RepositoryLocation repoModelsLocation;
private RepositoryLocation repoMessagesLocation;
@@ -116,8 +119,11 @@ public class RepoAdminServiceImpl implements RepoAdminService
this.messageService = messageService;
}
-
-
+ public void setRepoUsageComponent(RepoUsageComponent repoUsageComponent)
+ {
+ this.repoUsageComponent = repoUsageComponent;
+ }
+
public void setRepositoryModelsLocation(RepositoryLocation repoModelsLocation)
{
this.repoModelsLocation = repoModelsLocation;
@@ -128,11 +134,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
this.repoMessagesLocation = repoMessagesLocation;
}
-
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#getModels()
- */
public List getModels()
{
StoreRef storeRef = repoModelsLocation.getStoreRef();
@@ -198,10 +199,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
return modelsInRepo;
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#deployModel(java.io.InputStream, java.lang.String)
- */
public void deployModel(InputStream modelStream, String modelFileName)
{
try
@@ -294,10 +291,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
}
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#activateModel(java.lang.String)
- */
public QName activateModel(String modelFileName)
{
try
@@ -310,10 +303,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
}
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#deactivateModel(java.lang.String)
- */
public QName deactivateModel(String modelFileName)
{
try
@@ -424,10 +413,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
return modelQName;
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#undeployModel(java.lang.String)
- */
public QName undeployModel(String modelFileName)
{
// Check that all the passed values are not null
@@ -522,10 +507,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
return modelQName;
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#getMessageBundles()
- */
public List getMessageBundles()
{
StoreRef storeRef = repoMessagesLocation.getStoreRef();
@@ -580,10 +561,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
return resourceBundlesInRepo;
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#deployMessageBundle(java.lang.String)
- */
public String deployMessageBundle(String resourceClasspath)
{
// Check that all the passed values are not null
@@ -744,10 +721,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
}
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#undeployMessageBundle(java.lang.String)
- */
public void undeployMessageBundle(String bundleBaseName)
{
checkBundleBaseName(bundleBaseName);
@@ -792,10 +765,6 @@ public class RepoAdminServiceImpl implements RepoAdminService
}
}
- /*
- * (non-Javadoc)
- * @see org.alfresco.service.cmr.admin.RepoAdminService#reloadMessageBundle(java.lang.String)
- */
public void reloadMessageBundle(String bundleBaseName)
{
checkBundleBaseName(bundleBaseName);
@@ -860,4 +829,28 @@ public class RepoAdminServiceImpl implements RepoAdminService
throw new AlfrescoRuntimeException("Message deployment failed - bundle base name '" + bundleBaseName + "' should not contain '.' (period)");
}
}
+
+ @Override
+ public RepoUsage getRestrictions()
+ {
+ return repoUsageComponent.getRestrictions();
+ }
+
+ @Override
+ public RepoUsage getUsage()
+ {
+ return repoUsageComponent.getUsage();
+ }
+
+ @Override
+ public boolean updateUsage(UsageType usageType)
+ {
+ return repoUsageComponent.updateUsage(usageType);
+ }
+
+ @Override
+ public RepoUsageStatus getUsageStatus()
+ {
+ return repoUsageComponent.getUsageStatus();
+ }
}
diff --git a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
index 6b4a190351..ef47fed96b 100644
--- a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
@@ -32,6 +32,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.Tenant;
import org.alfresco.repo.tenant.TenantAdminService;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.admin.PatchException;
import org.alfresco.service.cmr.repository.NodeService;
@@ -92,6 +93,8 @@ public abstract class AbstractPatch implements Patch, ApplicationEventPublisher
private PatchService patchService;
/** used to ensure a unique transaction per execution */
protected TransactionService transactionService;
+ /** Use this helper to ensure that patches can execute even on a read-only system */
+ protected RetryingTransactionHelper transactionHelper;
protected NamespaceService namespaceService;
protected NodeService nodeService;
protected SearchService searchService;
@@ -140,6 +143,8 @@ public abstract class AbstractPatch implements Patch, ApplicationEventPublisher
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
+ this.transactionHelper = transactionService.getRetryingTransactionHelper();
+ this.transactionHelper.setForceWritable(true);
}
public void setNamespaceService(NamespaceService namespaceService)
@@ -378,6 +383,7 @@ public abstract class AbstractPatch implements Patch, ApplicationEventPublisher
checkPropertyNotNull(id, "id");
checkPropertyNotNull(description, "description");
checkPropertyNotNull(transactionService, "transactionService");
+ checkPropertyNotNull(transactionHelper, "transactionHelper");
checkPropertyNotNull(namespaceService, "namespaceService");
checkPropertyNotNull(nodeService, "nodeService");
checkPropertyNotNull(searchService, "searchService");
diff --git a/source/java/org/alfresco/repo/admin/patch/PatchExecuter.java b/source/java/org/alfresco/repo/admin/patch/PatchExecuter.java
index 05d387ec14..58dc427614 100644
--- a/source/java/org/alfresco/repo/admin/patch/PatchExecuter.java
+++ b/source/java/org/alfresco/repo/admin/patch/PatchExecuter.java
@@ -22,12 +22,13 @@ import java.util.Date;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
-import org.springframework.extensions.surf.util.I18NUtil;
-import org.alfresco.service.transaction.TransactionService;
-import org.springframework.extensions.surf.util.AbstractLifecycleBean;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
+import org.springframework.extensions.surf.util.AbstractLifecycleBean;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
* This component is responsible for ensuring that patches are applied
@@ -47,7 +48,6 @@ public class PatchExecuter extends AbstractLifecycleBean
private static Log logger = LogFactory.getLog(PatchExecuter.class);
private PatchService patchService;
- private TransactionService transactionService;
/**
* @param patchService the server that actually executes the patches
@@ -57,21 +57,14 @@ public class PatchExecuter extends AbstractLifecycleBean
this.patchService = patchService;
}
- /**
- * @param transactionService provides the system read-only state
- */
- public void setTransactionService(TransactionService transactionService)
- {
- this.transactionService = transactionService;
- }
-
/**
* Ensures that all outstanding patches are applied.
*/
public void applyOutstandingPatches()
{
- // Avoid read-only systems
- if (!patchService.validatePatches() || transactionService.isReadOnly())
+ // Apply patches even if we are in read only mode. The system may not work safely otherwise.
+
+ if (!patchService.validatePatches())
{
logger.warn(I18NUtil.getMessage(MSG_SYSTEM_READ_ONLY));
return;
@@ -123,7 +116,16 @@ public class PatchExecuter extends AbstractLifecycleBean
@Override
protected void onBootstrap(ApplicationEvent event)
{
- applyOutstandingPatches();
+ RunAsWork runPatches = new RunAsWork()
+ {
+ @Override
+ public Void doWork() throws Exception
+ {
+ applyOutstandingPatches();
+ return null;
+ }
+ };
+ AuthenticationUtil.runAs(runPatches, AuthenticationUtil.getSystemUserName());
}
@Override
@@ -131,5 +133,4 @@ public class PatchExecuter extends AbstractLifecycleBean
{
// NOOP
}
-
}
diff --git a/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java b/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java
index 0a16be71bd..b8cca69d8e 100644
--- a/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java
+++ b/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java
@@ -26,22 +26,21 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.transaction.UserTransaction;
-
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.domain.patch.AppliedPatchDAO;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
-import org.alfresco.repo.transaction.TransactionServiceImpl;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.repo.transaction.TransactionServiceImpl;
import org.alfresco.service.cmr.admin.PatchException;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.descriptor.DescriptorService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
-import org.springframework.transaction.PlatformTransactionManager;
/**
@@ -100,6 +99,9 @@ public class PatchServiceImpl implements PatchService
{
patches.add(patch);
}
+
+ private final QName vetoName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "PatchServiceImpl");
+
public boolean validatePatches()
{
@@ -117,7 +119,7 @@ public class PatchServiceImpl implements PatchService
}
if (!success)
{
- this.transactionService.setAllowWrite(false);
+ this.transactionService.setAllowWrite(false, vetoName);
}
return success;
}
@@ -405,7 +407,8 @@ public class PatchServiceImpl implements PatchService
*
* @return true: continue, false: do not apply patch
*/
- private void setup() {
+ private void setup()
+ {
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback