From 46046b574a80d686cf145587a858bd8844834701 Mon Sep 17 00:00:00 2001 From: strangeweaver Date: Thu, 18 Feb 2016 12:39:05 +0000 Subject: [PATCH] Implemented paged operations and used for database cleanup tasks. --- .../data/AbstractPageOperationTemplate.java | 160 ++++++++++++++ .../org/mitre/data/DefaultPageCriteria.java | 35 +++ .../java/org/mitre/data/PageCriteria.java | 13 ++ .../AuthenticationHolderRepository.java | 3 +- .../AuthorizationCodeRepository.java | 7 + .../repository/OAuth2TokenRepository.java | 5 + .../main/java/org/mitre/util/jpa/JpaUtil.java | 24 ++- .../AbstractPageOperationTemplateTest.java | 204 ++++++++++++++++++ .../JpaAuthenticationHolderRepository.java | 15 +- .../impl/JpaAuthorizationCodeRepository.java | 9 + .../impl/JpaOAuth2TokenRepository.java | 30 ++- ...DefaultOAuth2AuthorizationCodeService.java | 19 +- .../DefaultOAuth2ProviderTokenService.java | 68 +++--- 13 files changed, 534 insertions(+), 58 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java create mode 100644 openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java create mode 100644 openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java create mode 100644 openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java diff --git a/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java new file mode 100644 index 000000000..3a8962aac --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java @@ -0,0 +1,160 @@ +package org.mitre.data; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * Abstract class for performing an operation on a potentially large + * number of items by paging through the items in discreet chunks. + * + * @param the type parameter + * @author Colm Smyth. + */ +public abstract class AbstractPageOperationTemplate { + + private static final Logger logger = LoggerFactory.getLogger(AbstractPageOperationTemplate.class); + + private static int DEFAULT_MAX_PAGES = 1000; + private static long DEFAULT_MAX_TIME_MILLIS = 600000L; //10 Minutes + + /** + * int specifying the maximum number of + * pages which should be fetched before + * execution should terminate + */ + private int maxPages; + + /** + * long specifying the maximum execution time + * in milliseconds + */ + private long maxTime; + + /** + * boolean specifying whether or not Exceptions + * incurred performing the operation should be + * swallowed during execution default true. + */ + private boolean swallowExceptions = true; + + + /** + * default constructor which sets the value of + * maxPages and maxTime to DEFAULT_MAX_PAGES and + * DEFAULT_MAX_TIME_MILLIS respectively + */ + public AbstractPageOperationTemplate(){ + this(DEFAULT_MAX_PAGES, DEFAULT_MAX_TIME_MILLIS); + } + + + /** + * Instantiates a new AbstractPageOperationTemplate with the + * given maxPages and maxTime + * + * @param maxPages the maximum number of pages to fetch. + * @param maxTime the maximum execution time. + */ + public AbstractPageOperationTemplate(int maxPages, long maxTime){ + this.maxPages = maxPages; + this.maxTime = maxTime; + } + + + /** + * Execute the operation on each member of a page of results + * retrieved through the fetch method. the method will execute + * until either the maxPages or maxTime limit is reached or until + * the fetch method returns no more results. Exceptions thrown + * performing the operation on the item will be swallowed if the + * swallowException (default true) field is set true. + */ + public void execute(){ + logger.info("Starting execution of paged operation. maximum time: " + maxTime + + " maximum pages: " + maxPages); + + long startTime = System.currentTimeMillis(); + long executionTime = 0; + int i = 0; + + int exceptionsSwallowedCount = 0; + int operationsCompleted = 0; + Set exceptionsSwallowedClasses = new HashSet(); + + + while (i< maxPages && executionTime < maxTime){ + Collection page = fetchPage(); + if(page == null || page.size() == 0){ + break; + } + + for (T item : page) { + try { + doOperation(item); + operationsCompleted++; + } catch (Exception e){ + if(swallowExceptions){ + exceptionsSwallowedCount++; + exceptionsSwallowedClasses.add(e.getClass().getName()); + logger.debug("Swallowing exception " + e.getMessage(), e); + } else { + logger.debug("Rethrowing exception " + e.getMessage()); + throw e; + } + } + } + + i++; + executionTime = System.currentTimeMillis() - startTime; + } + + logger.info("Paged operation run completed " + operationsCompleted + " swallowed " + exceptionsSwallowedCount + " exceptions"); + for(String className: exceptionsSwallowedClasses) { + logger.warn("Paged operation swallowed at least one exception of type " + className); + } + } + + /** + * method responsible for fetching + * a page of items. + * + * @return the collection of items + */ + public abstract Collection fetchPage(); + + /** + * method responsible for performing desired + * operation on a fetched page item. + * + * @param item the item + */ + protected abstract void doOperation(T item); + + public int getMaxPages() { + return maxPages; + } + + public void setMaxPages(int maxPages) { + this.maxPages = maxPages; + } + + public long getMaxTime() { + return maxTime; + } + + public void setMaxTime(long maxTime) { + this.maxTime = maxTime; + } + + public boolean isSwallowExceptions() { + return swallowExceptions; + } + + public void setSwallowExceptions(boolean swallowExceptions) { + this.swallowExceptions = swallowExceptions; + } +} diff --git a/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java new file mode 100644 index 000000000..fc559c5e4 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java @@ -0,0 +1,35 @@ +package org.mitre.data; + +/** + * Default implementation of PageCriteria which specifies + * both page to be retrieved and page size in the constructor. + * + * @author Colm Smyth + */ +public class DefaultPageCriteria implements PageCriteria { + + private static final int DEFAULT_PAGE_NUMBER = 0; + private static final int DEFAULT_PAGE_SIZE = 100; + + private int pageNumber; + private int pageSize; + + public DefaultPageCriteria(){ + this(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE); + } + + public DefaultPageCriteria(int pageNumber, int pageSize) { + this.pageNumber = pageNumber; + this.pageSize = pageSize; + } + + @Override + public int getPageNumber() { + return pageNumber; + } + + @Override + public int getPageSize() { + return pageSize; + } +} diff --git a/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java new file mode 100644 index 000000000..f9f57562f --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java @@ -0,0 +1,13 @@ +package org.mitre.data; + +/** + * Interface which defines page criteria for use in + * a repository operation. + * + * @author Colm Smyth + */ +public interface PageCriteria { + + public int getPageNumber(); + public int getPageSize(); +} diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java index 3725e6e8c..af811430d 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java @@ -18,6 +18,7 @@ package org.mitre.oauth2.repository; import java.util.List; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.AuthenticationHolderEntity; public interface AuthenticationHolderRepository { @@ -31,5 +32,5 @@ public interface AuthenticationHolderRepository { public List getOrphanedAuthenticationHolders(); - + public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria); } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java index e98c52f23..9d056abbe 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java @@ -18,6 +18,7 @@ package org.mitre.oauth2.repository; import java.util.Collection; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.AuthorizationCodeEntity; /** @@ -56,4 +57,10 @@ public interface AuthorizationCodeRepository { */ public Collection getExpiredCodes(); + /** + * @return A collection of all expired codes, limited by the given + * PageCriteria. + */ + public Collection getExpiredCodes(PageCriteria pageCriteria); + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java index 5afc5def3..9c4ac7b26 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java @@ -19,6 +19,7 @@ package org.mitre.oauth2.repository; import java.util.List; import java.util.Set; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; @@ -57,8 +58,12 @@ public interface OAuth2TokenRepository { public Set getAllExpiredAccessTokens(); + public Set getAllExpiredAccessTokens(PageCriteria pageCriteria); + public Set getAllExpiredRefreshTokens(); + public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria); + public Set getAccessTokensForResourceSet(ResourceSet rs); /** diff --git a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java index 2ac846360..0295c691b 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java +++ b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java @@ -16,9 +16,12 @@ *******************************************************************************/ package org.mitre.util.jpa; +import org.mitre.data.PageCriteria; + import java.util.List; import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; /** * @author mfranklin @@ -26,7 +29,7 @@ import javax.persistence.EntityManager; * Time: 2:13 PM */ public class JpaUtil { - public static T getSingleResult(List list) { + public static T getSingleResult(List list) { switch(list.size()) { case 0: return null; @@ -37,6 +40,25 @@ public class JpaUtil { } } + + /** + * Get a page of results from the specified TypedQuery + * by using the given PageCriteria to limit the query + * results. The PageCriteria will override any size or + * offset already specified on the query. + * + * @param the type parameter + * @param query the query + * @param pageCriteria the page criteria + * @return the list + */ + public static List getResultPage(TypedQuery query, PageCriteria pageCriteria){ + query.setMaxResults(pageCriteria.getPageSize()); + query.setFirstResult(pageCriteria.getPageNumber()*pageCriteria.getPageSize()); + + return query.getResultList(); + } + public static T saveOrUpdate(I id, EntityManager entityManager, T entity) { T tmp = entityManager.merge(entity); entityManager.flush(); diff --git a/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java new file mode 100644 index 000000000..1aaa46869 --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java @@ -0,0 +1,204 @@ +package org.mitre.data; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Colm Smyth + */ +public class AbstractPageOperationTemplateTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void execute_zeropages() { + CountingPageOperation op = new CountingPageOperation(0,Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.counter); + } + + @Test + public void execute_singlepage() { + CountingPageOperation op = new CountingPageOperation(1,Long.MAX_VALUE); + op.execute(); + + assertEquals(10L, op.counter); + } + + @Test + public void execute_negpage() { + CountingPageOperation op = new CountingPageOperation(-1,Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.counter); + } + + @Test + public void execute_npage(){ + int n = 7; + CountingPageOperation op = new CountingPageOperation(n,Long.MAX_VALUE); + op.execute(); + + assertEquals(n*10L, op.counter); + } + + @Test + public void execute_nullpage(){ + CountingPageOperation op = new NullPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test + public void execute_emptypage(){ + CountingPageOperation op = new EmptyPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test + public void execute_zerotime(){ + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,0L); + op.execute(); + + assertEquals(0L, op.getCounter()); + assertEquals(0L, op.getLastFetchTime()); + } + + @Test + public void execute_nonzerotime(){ + Long timeMillis = 100L; + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); + op.execute(); + + assertTrue("start time " + op.getStartTime() + "" + + " to last fetch time " + op.getLastFetchTime() + + " exceeds max time" + timeMillis, op.getLastFetchTime() - op.getStartTime() <= timeMillis); + } + + @Test + public void execute_negtime(){ + Long timeMillis = -100L; + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test + public void execute_swallowException(){ + CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); + op.execute(); + + assertTrue(op.isSwallowExceptions()); + assertEquals(5L, op.getCounter()); + } + + @Test(expected = IllegalStateException.class) + public void execute_noSwallowException(){ + CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); + op.setSwallowExceptions(false); + + try { + op.execute(); + }finally { + assertEquals(1L, op.getCounter()); + } + } + + + private static class CountingPageOperation extends AbstractPageOperationTemplate{ + + private int currentPageFetch; + private int pageSize = 10; + private long counter = 0L; + private long startTime; + private long lastFetchTime; + + private CountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + startTime = System.currentTimeMillis(); + } + + @Override + public Collection fetchPage() { + lastFetchTime = System.currentTimeMillis(); + List page = new ArrayList<>(pageSize); + for(int i = 0; i < pageSize; i++ ) { + page.add("item " + currentPageFetch * pageSize + i); + } + currentPageFetch++; + return page; + } + + @Override + protected void doOperation(String item) { + counter++; + } + + public long getCounter() { + return counter; + } + + public long getLastFetchTime() { + return lastFetchTime; + } + + public long getStartTime(){ + return startTime; + } + } + + private static class NullPageCountingPageOperation extends CountingPageOperation { + private NullPageCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + public Collection fetchPage() { + return null; + } + } + + private static class EmptyPageCountingPageOperation extends CountingPageOperation { + private EmptyPageCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + public Collection fetchPage() { + return new ArrayList<>(0); + } + } + + private static class EvenExceptionCountingPageOperation extends CountingPageOperation { + + private int callCounter; + private EvenExceptionCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + protected void doOperation(String item) { + callCounter++; + if(callCounter%2 == 0){ + throw new IllegalStateException("even number items cannot be processed"); + } + + super.doOperation(item); + + } + } +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java index 602302c6e..7597c79b6 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java @@ -22,6 +22,8 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; +import org.mitre.data.DefaultPageCriteria; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.AuthenticationHolderEntity; import org.mitre.oauth2.repository.AuthenticationHolderRepository; import org.mitre.util.jpa.JpaUtil; @@ -68,10 +70,15 @@ public class JpaAuthenticationHolderRepository implements AuthenticationHolderRe @Override @Transactional(value="defaultTransactionManager") public List getOrphanedAuthenticationHolders() { - TypedQuery query = manager.createNamedQuery(AuthenticationHolderEntity.QUERY_GET_UNUSED, AuthenticationHolderEntity.class); - query.setMaxResults(MAXEXPIREDRESULTS); - List unusedAuthenticationHolders = query.getResultList(); - return unusedAuthenticationHolders; + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0,MAXEXPIREDRESULTS); + return getOrphanedAuthenticationHolders(pageCriteria); } + @Override + @Transactional(value="defaultTransactionManager") + public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(AuthenticationHolderEntity.QUERY_GET_UNUSED, AuthenticationHolderEntity.class); + return JpaUtil.getResultPage(query, pageCriteria); + } + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java index 59623c9e1..ffaef9021 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java @@ -26,6 +26,7 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.AuthorizationCodeEntity; import org.mitre.oauth2.repository.AuthorizationCodeRepository; import org.mitre.util.jpa.JpaUtil; @@ -91,5 +92,13 @@ public class JpaAuthorizationCodeRepository implements AuthorizationCodeReposito } + @Override + public Collection getExpiredCodes(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(AuthorizationCodeEntity.QUERY_EXPIRATION_BY_DATE, AuthorizationCodeEntity.class); + query.setParameter(AuthorizationCodeEntity.PARAM_DATE, new Date()); // this gets anything that's already expired + return JpaUtil.getResultPage(query, pageCriteria); + } + + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index d10480e16..c851d2ee9 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -31,6 +31,8 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.Root; +import org.mitre.data.DefaultPageCriteria; +import org.mitre.data.PageCriteria; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; @@ -189,20 +191,32 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { @Override public Set getAllExpiredAccessTokens() { - TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2AccessTokenEntity.class); - query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); - query.setMaxResults(MAXEXPIREDRESULTS); - return new LinkedHashSet<>(query.getResultList()); + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); + return getAllExpiredAccessTokens(pageCriteria); } + @Override + public Set getAllExpiredAccessTokens(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2AccessTokenEntity.class); + query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); + return new LinkedHashSet<>(JpaUtil.getResultPage(query, pageCriteria)); + } + @Override public Set getAllExpiredRefreshTokens() { - TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2RefreshTokenEntity.class); - query.setParameter(OAuth2RefreshTokenEntity.PARAM_DATE, new Date()); - query.setMaxResults(MAXEXPIREDRESULTS); - return new LinkedHashSet<>(query.getResultList()); + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); + return getAllExpiredRefreshTokens(pageCriteria); } + @Override + public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2RefreshTokenEntity.class); + query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); + return new LinkedHashSet<>(JpaUtil.getResultPage(query,pageCriteria)); + } + + + /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokensForResourceSet(org.mitre.uma.model.ResourceSet) */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java index d6445d1bc..5312f52ff 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java @@ -22,6 +22,7 @@ package org.mitre.oauth2.service.impl; import java.util.Collection; import java.util.Date; +import org.mitre.data.AbstractPageOperationTemplate; import org.mitre.oauth2.model.AuthenticationHolderEntity; import org.mitre.oauth2.model.AuthorizationCodeEntity; import org.mitre.oauth2.repository.AuthenticationHolderRepository; @@ -116,15 +117,17 @@ public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeS @Transactional(value="defaultTransactionManager") public void clearExpiredAuthorizationCodes() { - Collection codes = repository.getExpiredCodes(); + new AbstractPageOperationTemplate(){ + @Override + public Collection fetchPage() { + return repository.getExpiredCodes(); + } - for (AuthorizationCodeEntity code : codes) { - repository.remove(code); - } - - if (codes.size() > 0) { - logger.info("Removed " + codes.size() + " expired authorization codes."); - } + @Override + protected void doOperation(AuthorizationCodeEntity item) { + repository.remove(item); + } + }.execute(); } /** diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index 8bfcd970b..a4d72c4fc 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -33,6 +33,8 @@ import java.util.List; import java.util.Set; import java.util.UUID; +import org.mitre.data.AbstractPageOperationTemplate; +import org.mitre.data.DefaultPageCriteria; import org.mitre.oauth2.model.AuthenticationHolderEntity; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; @@ -490,47 +492,41 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi public void clearExpiredTokens() { logger.debug("Cleaning out all expired tokens"); - Collection accessTokens = getExpiredAccessTokens(); - if (accessTokens.size() > 0) { - logger.info("Found " + accessTokens.size() + " expired access tokens"); - } - for (OAuth2AccessTokenEntity oAuth2AccessTokenEntity : accessTokens) { - try { - revokeAccessToken(oAuth2AccessTokenEntity); - } catch (IllegalArgumentException e) { - //An ID token is deleted with its corresponding access token, but then the ID token is on the list of expired tokens as well and there is - //nothing in place to distinguish it from any other. - //An attempt to delete an already deleted token returns an error, stopping the cleanup dead. We need it to keep going. - } - } + new AbstractPageOperationTemplate() { + @Override + public Collection fetchPage() { + return tokenRepository.getAllExpiredAccessTokens(new DefaultPageCriteria()); + } - Collection refreshTokens = getExpiredRefreshTokens(); - if (refreshTokens.size() > 0) { - logger.info("Found " + refreshTokens.size() + " expired refresh tokens"); - } - for (OAuth2RefreshTokenEntity oAuth2RefreshTokenEntity : refreshTokens) { - revokeRefreshToken(oAuth2RefreshTokenEntity); - } + @Override + public void doOperation(OAuth2AccessTokenEntity item) { + revokeAccessToken(item); + } + }.execute(); - Collection authHolders = getOrphanedAuthenticationHolders(); - if (authHolders.size() > 0) { - logger.info("Found " + authHolders.size() + " orphaned authentication holders"); - } - for(AuthenticationHolderEntity authHolder : authHolders) { - authenticationHolderRepository.remove(authHolder); - } - } + new AbstractPageOperationTemplate() { + @Override + public Collection fetchPage() { + return tokenRepository.getAllExpiredRefreshTokens(new DefaultPageCriteria()); + } - private Collection getExpiredAccessTokens() { - return Sets.newHashSet(tokenRepository.getAllExpiredAccessTokens()); - } + @Override + public void doOperation(OAuth2RefreshTokenEntity item) { + revokeRefreshToken(item); + } + }.execute(); - private Collection getExpiredRefreshTokens() { - return Sets.newHashSet(tokenRepository.getAllExpiredRefreshTokens()); - } + new AbstractPageOperationTemplate() { + @Override + public Collection fetchPage() { + return authenticationHolderRepository.getOrphanedAuthenticationHolders(new DefaultPageCriteria()); + } - private Collection getOrphanedAuthenticationHolders() { - return Sets.newHashSet(authenticationHolderRepository.getOrphanedAuthenticationHolders()); + @Override + public void doOperation(AuthenticationHolderEntity item) { + authenticationHolderRepository.remove(item); + } + }.execute(); } /* (non-Javadoc)