mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-01 14:41:46 +00:00
Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
812541870e | ||
|
9aa5051826 | ||
|
54580b4aeb | ||
|
2b1b6091a3 | ||
|
74a147ab3f | ||
|
07f0595f5a | ||
|
e3422ea6a5 | ||
|
f4103c242f | ||
|
34fb5e9dd9 | ||
|
f6cf0670c1 | ||
|
c7bd036030 | ||
|
b20c573040 | ||
|
6568885c10 | ||
|
31237135c5 | ||
|
d528ed1e97 | ||
|
bb207340fd | ||
|
314e1aeb64 | ||
|
9846f7b04f | ||
|
6e442e93b8 | ||
|
fb3c57aab4 | ||
|
093b3281fb | ||
|
3b027c6c36 | ||
|
f193309e4c | ||
|
7668849a59 | ||
|
1350e68c29 | ||
|
ea63cf76e5 | ||
|
674fa8d7e0 | ||
|
60a31112ea | ||
|
67d8807529 | ||
|
dda1fd6ea3 | ||
|
7a937f1e51 | ||
|
187e9138da |
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -45,13 +45,13 @@ public class RestPersonFavoritesModel extends TestModel implements IRestModel<Re
|
||||
|
||||
private String targetGuid;
|
||||
private String createdAt;
|
||||
private List<String> aspectNames;
|
||||
private List<String> allowableOperations;
|
||||
|
||||
private RestTargetModel target;
|
||||
|
||||
public RestPersonFavoritesModel()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
public RestPersonFavoritesModel(String targetGuid, String createdAt)
|
||||
{
|
||||
@@ -90,11 +90,23 @@ public class RestPersonFavoritesModel extends TestModel implements IRestModel<Re
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public List<String> getAllowableOperations() {
|
||||
public List<String> getAspectNames()
|
||||
{
|
||||
return aspectNames;
|
||||
}
|
||||
|
||||
public void setAspectNames(List<String> aspectNames)
|
||||
{
|
||||
this.aspectNames = aspectNames;
|
||||
}
|
||||
|
||||
public List<String> getAllowableOperations()
|
||||
{
|
||||
return allowableOperations;
|
||||
}
|
||||
|
||||
public void setAllowableOperations(List<String> allowableOperations) {
|
||||
public void setAllowableOperations(List<String> allowableOperations)
|
||||
{
|
||||
this.allowableOperations = allowableOperations;
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,11 @@ package org.alfresco.rest.favorites;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil.DocumentType;
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestErrorModel;
|
||||
@@ -20,14 +25,11 @@ import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.alfresco.utility.testrail.ExecutionType;
|
||||
import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class GetFavoritesTests extends RestTest
|
||||
{
|
||||
private static final String ALLOWABLE_OPERATIONS = "allowableOperations";
|
||||
private static final String ASPECT_NAMES = "aspectNames";
|
||||
private UserModel adminUserModel, userModel;
|
||||
private SiteModel firstSiteModel;
|
||||
private SiteModel secondSiteModel;
|
||||
@@ -64,9 +66,9 @@ public class GetFavoritesTests extends RestTest
|
||||
restClient.withCoreAPI().usingUser(userModel).addSiteToFavorites(thirdSiteModel);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.SANITY,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.SANITY,
|
||||
description = "Verify Manager user gets favorites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.SANITY })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.SANITY})
|
||||
public void managerIsAbleToRetrieveFavorites()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -79,10 +81,10 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertThat().entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.SANITY,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.SANITY,
|
||||
description = "Verify user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.SANITY })
|
||||
// @Bug(id = "MNT-16904", description = "It fails only on environment with tenants")
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.SANITY})
|
||||
// @Bug(id = "MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void userIsNotAbleToRetrieveFavoritesIfAuthenticationFails()
|
||||
{
|
||||
UserModel siteManager = firstSiteUsers.getOneUserWithRole(UserRole.SiteManager);
|
||||
@@ -91,9 +93,9 @@ public class GetFavoritesTests extends RestTest
|
||||
restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user gets favorites sites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void adminIsAbleToRetrieveFavoritesSites()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingUser(adminUserModel).addSiteToFavorites(firstSiteModel);
|
||||
@@ -106,9 +108,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user gets favorites folders with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void adminIsAbleToRetrieveFavoritesFolders()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingUser(adminUserModel).addFolderToFavorites(firstFolderModel);
|
||||
@@ -121,9 +123,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListContains("targetGuid", secondFolderModel.getNodeRef());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user gets favorites files with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void adminIsAbleToRetrieveFavoritesFiles()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingUser(adminUserModel).addFileToFavorites(firstFileModel);
|
||||
@@ -136,9 +138,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListContains("targetGuid", secondFileModel.getNodeRefWithoutVersion());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Collaborator user gets favorites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void collaboratorIsAbleToRetrieveFavorites()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator))
|
||||
@@ -151,9 +153,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user gets favorites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void contributorIsAbleToRetrieveFavorites()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteContributor))
|
||||
@@ -166,9 +168,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Consumer user gets favorites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void consumerIsAbleToRetrieveFavorites()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteConsumer))
|
||||
@@ -181,9 +183,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertThat().entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify user doesn't have permission to get favorites of another user with Rest API and status code is 404")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsNotAbleToRetrieveFavoritesOfAnotherUser()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteConsumer))
|
||||
@@ -192,9 +194,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator).getUsername()));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify user doesn't have permission to get favorites of admin user with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsNotAbleToRetrieveFavoritesOfAdminUser()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteConsumer)).withCoreAPI()
|
||||
@@ -203,9 +205,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, adminUserModel.getUsername()));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user doesn't have permission to get favorites of another user with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void adminIsNotAbleToRetrieveFavoritesOfAnotherUser()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator))
|
||||
@@ -214,9 +216,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator).getUsername()));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites sites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveOnlyFavoritesSites()
|
||||
{
|
||||
restClient.authenticateUser(secondSiteUsers.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -232,9 +234,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstFolderModel.getNodeRef());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites files with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveOnlyFavoritesFiles()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
@@ -250,9 +252,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstFolderModel.getNodeRef());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites folders with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveOnlyFavoritesFolders()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
@@ -268,9 +270,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstFileModel.getNodeRefWithoutVersion());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites files or folders with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveFavoritesFilesOrFolders()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
@@ -289,9 +291,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites files or sites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveFavoritesFilesOrSites()
|
||||
{
|
||||
restClient.authenticateUser(secondSiteUsers.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -310,9 +312,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstFolderModel.getNodeRef());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets only favorites folders or sites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveFavoritesFoldersOrSites()
|
||||
{
|
||||
restClient.authenticateUser(secondSiteUsers.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -331,9 +333,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", firstFileModel.getNodeRefWithoutVersion());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets all favorites with Rest API and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToRetrieveAllFavorites()
|
||||
{
|
||||
restClient.authenticateUser(secondSiteUsers.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
@@ -362,9 +364,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", secondFileModel.getNodeRefWithoutVersion());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify request for a user with no favorites returns status 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userHasNoFavorites()
|
||||
{
|
||||
restClient.authenticateUser(secondSiteUsers.getOneUserWithRole(UserRole.SiteContributor));
|
||||
@@ -374,9 +376,9 @@ public class GetFavoritesTests extends RestTest
|
||||
userFavorites.assertThat().entriesListIsEmpty().and().paginationField("totalItems").is("0");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify request using invalid where parameter returns status 400")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void getFavoritesUsingInvalidWhereParameter()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
@@ -390,9 +392,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_ARGUMENT, "WHERE query"));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify User gets correct favorites after deleting a favorite")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void checkFavoriteFolderIsRemoved()
|
||||
{
|
||||
restClient.authenticateUser(firstSiteUsers.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -408,9 +410,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().paginationField("totalItems").is("2");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites specifying -me- string in place of <personid> for request")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesWhenUsingMeAsUsername()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withCoreAPI().usingMe().getFavorites();
|
||||
@@ -418,9 +420,9 @@ public class GetFavoritesTests extends RestTest
|
||||
userFavorites.assertThat().entriesListContains("targetGuid", firstSiteModel.getGuid()).and().entriesListContains("targetGuid", secondSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites using empty for where parameter for request")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesWhenUsingEmptyWhereParameter()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(adminUserModel).withCoreAPI().usingAuthUser().where().getFavorites();
|
||||
@@ -428,27 +430,27 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_ARGUMENT, "WHERE query"));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API,TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that for invalid maxItems parameter status code returned is 400.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void checkInvalidMaxItemsStatusCode()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withParams("maxItems=AB").withCoreAPI().usingUser(adminUserModel).getFavorites();
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST).assertLastError().containsSummary("Invalid paging parameter");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API,TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that for invalid skipCount parameter status code returned is 400.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void checkInvalidSkipCountStatusCode()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withParams("skipCount=AB").withCoreAPI().usingUser(adminUserModel).getFavorites();
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST).assertLastError().containsSummary("Invalid paging parameter");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites when using invalid network id for non-tenant user")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void getFavoritesWhenNetworkIdIsInvalid()
|
||||
{
|
||||
UserModel networkUserModel = dataUser.createRandomTestUser();
|
||||
@@ -457,9 +459,9 @@ public class GetFavoritesTests extends RestTest
|
||||
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND).assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, networkUserModel.getUsername()));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites using AND instead of OR in where parameter for request")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsNotAbleToGetFavoritesWhenUsingANDInWhereParameter()
|
||||
{
|
||||
userFavorites = restClient.withCoreAPI().usingAuthUser().where().targetFolderExist().invalidWhereParameter("AND").targetFileExist().getFavorites();
|
||||
@@ -467,9 +469,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_ARGUMENT, "WHERE query"));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites using wrong name instead of EXISTS in where parameter for request")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsNotAbleToGetFavoritesWhenUsingWrongWhereParameter()
|
||||
{
|
||||
userFavorites = restClient.withCoreAPI().usingAuthUser().where().invalidWhereParameter("EXIST((target/site))").targetFileExist().getFavorites();
|
||||
@@ -477,9 +479,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_ARGUMENT, "WHERE query"));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites except the first one for request")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesExceptTheFirstOne()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withParams("skipCount=1").withCoreAPI().usingUser(userModel).getFavorites();
|
||||
@@ -490,9 +492,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().entriesListDoesNotContain("targetGuid", thirdSiteModel.getGuid());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get first two favorites sites")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFirstTwoFavorites()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withParams("maxItems=2").withCoreAPI().usingUser(userModel).getFavorites();
|
||||
@@ -506,9 +508,9 @@ public class GetFavoritesTests extends RestTest
|
||||
.and().field("count").is("2");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify get favorites sites when using empty values for skipCount and maxItems")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesWhenSkipCountAndMaxItemsAreEmpty()
|
||||
{
|
||||
restClient.authenticateUser(userModel).withParams("skipCount= ").withCoreAPI().usingUser(userModel).getFavorites();
|
||||
@@ -518,9 +520,9 @@ public class GetFavoritesTests extends RestTest
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST).assertLastError().containsSummary(String.format(RestErrorModel.INVALID_MAXITEMS, " "));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify the get favorites request for a high value for skipCount parameter")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesWithHighSkipCount()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withParams("skipCount=999999999").withCoreAPI().usingUser(userModel).getFavorites();
|
||||
@@ -529,9 +531,9 @@ public class GetFavoritesTests extends RestTest
|
||||
userFavorites.assertThat().entriesListIsEmpty().assertThat().paginationField("skipCount").is("999999999");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify the get favorites request with properties parameter applied")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void userIsAbleToGetFavoritesWithPropertiesParamApplied()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withParams("properties=targetGuid").withCoreAPI().usingUser(userModel).getFavorites();
|
||||
@@ -541,8 +543,8 @@ public class GetFavoritesTests extends RestTest
|
||||
restPersonFavoritesModel.assertThat().field("targetGuid").is(thirdSiteModel.getGuid()).and().field("createdAt").isNull();
|
||||
}
|
||||
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION, description = "Verify entry details for get favorites response with Rest API")
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION, description = "Verify entry details for get favorites response with Rest API")
|
||||
public void checkResponseSchemaForGetFavorites()
|
||||
{
|
||||
userFavorites = restClient.authenticateUser(userModel).withCoreAPI().usingAuthUser().getFavorites();
|
||||
@@ -564,8 +566,7 @@ public class GetFavoritesTests extends RestTest
|
||||
description = "Verify if get favorites response returns allowableOperations object when requested")
|
||||
public void checkResponsesForGetFavoritesWithAllowableOperations()
|
||||
{
|
||||
final RestPersonFavoritesModelsCollection adminFavorites =
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingAuthUser().include(ALLOWABLE_OPERATIONS).getFavorites();
|
||||
final RestPersonFavoritesModelsCollection adminFavorites = restClient.authenticateUser(adminUserModel).withCoreAPI().usingAuthUser().include(ALLOWABLE_OPERATIONS).getFavorites();
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
adminFavorites.getEntries().stream()
|
||||
@@ -576,18 +577,30 @@ public class GetFavoritesTests extends RestTest
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify the get favorites request with properties parameter applied")
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
public void checkSearchResponseContainsIsFavoriteWhenRequested() throws InterruptedException {
|
||||
public void checkSearchResponseContainsIsFavoriteWhenRequested() throws InterruptedException
|
||||
{
|
||||
final SearchRequest query = new SearchRequest();
|
||||
final RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
queryReq.setQuery(firstFileModel.getName());
|
||||
query.setQuery(queryReq);
|
||||
query.setInclude(List.of("isFavorite"));
|
||||
|
||||
Utility.sleep(500, 60000, () ->
|
||||
{
|
||||
Utility.sleep(500, 60000, () -> {
|
||||
restClient.authenticateUser(adminUserModel).withSearchAPI().search(query);
|
||||
restClient.onResponse().assertThat().body("list.entries.entry[0].isFavorite", Matchers.notNullValue());
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION})
|
||||
@TestRail(section = {TestGroup.REST_API, TestGroup.FAVORITES}, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify if get favorites response returns aspectNames when requested")
|
||||
public void checkResponsesForGetFavoritesWithAspectNames()
|
||||
{
|
||||
final RestPersonFavoritesModelsCollection adminFavorites = restClient.authenticateUser(adminUserModel).withCoreAPI().usingAuthUser().include(ASPECT_NAMES).getFavorites();
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
adminFavorites.getEntries().stream()
|
||||
.map(RestPersonFavoritesModel::onModel)
|
||||
.forEach(m -> m.assertThat().field(ASPECT_NAMES).isNotEmpty());
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
12
pom.xml
12
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
||||
<dependency.cxf.version>4.0.5</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>9.3</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>9.4</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>5.14.1</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.26.3</dependency.assertj.version>
|
||||
<dependency.org-json.version>20240303</dependency.org-json.version>
|
||||
<dependency.commons-dbcp.version>2.12.0</dependency.commons-dbcp.version>
|
||||
<dependency.commons-io.version>2.16.1</dependency.commons-io.version>
|
||||
<dependency.commons-io.version>2.17.0</dependency.commons-io.version>
|
||||
<dependency.gson.version>2.11.0</dependency.gson.version>
|
||||
<dependency.guava.version>33.3.1-jre</dependency.guava.version>
|
||||
<dependency.httpclient.version>4.5.14</dependency.httpclient.version>
|
||||
@@ -113,7 +113,7 @@
|
||||
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
|
||||
<dependency.json-smart.version>2.5.1</dependency.json-smart.version>
|
||||
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>3.1.0</alfresco.aos-module.version>
|
||||
<alfresco.aos-module.version>4.0.0-A1</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>23.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
|
||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||
@@ -154,7 +154,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>23.4.0.37</tag>
|
||||
<tag>23.4.0.46</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -1015,7 +1015,7 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -26,6 +26,7 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static org.alfresco.rest.api.Nodes.PARAM_INCLUDE_ALLOWABLEOPERATIONS;
|
||||
import static org.alfresco.rest.api.Nodes.PARAM_INCLUDE_ASPECTNAMES;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
@@ -38,6 +39,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingResults;
|
||||
@@ -77,9 +80,6 @@ import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Public REST API: Centralises access to favourites functionality and maps between representations repository and api representations.
|
||||
@@ -89,9 +89,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
*/
|
||||
public class FavouritesImpl implements Favourites
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(FavouritesImpl.class);
|
||||
|
||||
private static final List<String> ALLOWED_INCLUDES = List.of(PARAM_INCLUDE_PROPERTIES, PARAM_INCLUDE_ALLOWABLEOPERATIONS);
|
||||
private static final List<String> ALLOWED_INCLUDES = List.of(PARAM_INCLUDE_PROPERTIES, PARAM_INCLUDE_ASPECTNAMES, PARAM_INCLUDE_ALLOWABLEOPERATIONS);
|
||||
|
||||
private People people;
|
||||
private Sites sites;
|
||||
@@ -105,8 +103,7 @@ public class FavouritesImpl implements Favourites
|
||||
ContentModel.PROP_TITLE,
|
||||
ContentModel.PROP_DESCRIPTION,
|
||||
SiteModel.PROP_SITE_VISIBILITY,
|
||||
SiteModel.PROP_SITE_PRESET
|
||||
);
|
||||
SiteModel.PROP_SITE_PRESET);
|
||||
|
||||
public void setPeople(People people)
|
||||
{
|
||||
@@ -140,22 +137,22 @@ public class FavouritesImpl implements Favourites
|
||||
|
||||
private Target getTarget(PersonFavourite personFavourite, Parameters parameters)
|
||||
{
|
||||
Target target = null;
|
||||
Target target;
|
||||
NodeRef nodeRef = personFavourite.getNodeRef();
|
||||
Type type = personFavourite.getType();
|
||||
if(type.equals(Type.FILE))
|
||||
if (type.equals(Type.FILE))
|
||||
{
|
||||
Document document = nodes.getDocument(nodeRef);
|
||||
setPathInfo(document, parameters.getInclude());
|
||||
target = new DocumentTarget(document);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
else if (type.equals(Type.FOLDER))
|
||||
{
|
||||
Folder folder = nodes.getFolder(nodeRef);
|
||||
setPathInfo(folder, parameters.getInclude());
|
||||
target = new FolderTarget(folder);
|
||||
}
|
||||
else if(type.equals(Type.SITE))
|
||||
else if (type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
String role = sites.getSiteRole(siteInfo.getShortName());
|
||||
@@ -182,15 +179,19 @@ public class FavouritesImpl implements Favourites
|
||||
final List<String> paramsInclude = parameters.getInclude();
|
||||
if (!Collections.disjoint(paramsInclude, ALLOWED_INCLUDES))
|
||||
{
|
||||
final List<String> includes = ALLOWED_INCLUDES.stream().filter(a -> paramsInclude.contains(a)).collect(Collectors.toList());
|
||||
final List<String> includes = ALLOWED_INCLUDES.stream().filter(paramsInclude::contains).collect(Collectors.toList());
|
||||
// get node representation with only properties included
|
||||
Node node = nodes.getFolderOrDocument(personFavourite.getNodeRef(), null, null, includes, null);
|
||||
// Create a map from node properties excluding properties already in this Favorite
|
||||
Map<String, Object> filteredNodeProperties = filterProps(node.getProperties(), EXCLUDED_PROPS);
|
||||
if(filteredNodeProperties.size() > 0 && paramsInclude.contains(PARAM_INCLUDE_PROPERTIES))
|
||||
if (!filteredNodeProperties.isEmpty() && paramsInclude.contains(PARAM_INCLUDE_PROPERTIES))
|
||||
{
|
||||
fav.setProperties(filteredNodeProperties);
|
||||
}
|
||||
if (paramsInclude.contains(PARAM_INCLUDE_ASPECTNAMES))
|
||||
{
|
||||
fav.setAspectNames(node.getAspectNames());
|
||||
}
|
||||
final List<String> allowableOperations = node.getAllowableOperations();
|
||||
if (CollectionUtils.isNotEmpty(allowableOperations) && paramsInclude.contains(PARAM_INCLUDE_ALLOWABLEOPERATIONS))
|
||||
{
|
||||
@@ -212,8 +213,7 @@ public class FavouritesImpl implements Favourites
|
||||
private CollectionWithPagingInfo<Favourite> wrap(Paging paging, PagingResults<PersonFavourite> personFavourites, Parameters parameters)
|
||||
{
|
||||
final List<PersonFavourite> page = personFavourites.getPage();
|
||||
final List<Favourite> list = new AbstractList<Favourite>()
|
||||
{
|
||||
final List<Favourite> list = new AbstractList<>() {
|
||||
@Override
|
||||
public Favourite get(int index)
|
||||
{
|
||||
@@ -230,7 +230,7 @@ public class FavouritesImpl implements Favourites
|
||||
};
|
||||
Pair<Integer, Integer> pair = personFavourites.getTotalResultCount();
|
||||
Integer total = null;
|
||||
if(pair.getFirst().equals(pair.getSecond()))
|
||||
if (pair.getFirst().equals(pair.getSecond()))
|
||||
{
|
||||
total = pair.getFirst();
|
||||
}
|
||||
@@ -251,13 +251,13 @@ public class FavouritesImpl implements Favourites
|
||||
|
||||
personId = people.validatePerson(personId, true);
|
||||
Target target = favourite.getTarget();
|
||||
if(target == null)
|
||||
if (target == null)
|
||||
{
|
||||
throw new InvalidArgumentException("target is missing");
|
||||
}
|
||||
else if(target instanceof SiteTarget)
|
||||
else if (target instanceof SiteTarget)
|
||||
{
|
||||
SiteTarget siteTarget = (SiteTarget)target;
|
||||
SiteTarget siteTarget = (SiteTarget) target;
|
||||
String guid = siteTarget.getSite().getGuid();
|
||||
SiteInfo siteInfo = sites.validateSite(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, guid));
|
||||
NodeRef siteNodeRef = siteInfo.getNodeRef();
|
||||
@@ -268,16 +268,16 @@ public class FavouritesImpl implements Favourites
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, siteNodeRef);
|
||||
ret = getFavourite(personFavourite, parameters);
|
||||
}
|
||||
catch(SiteDoesNotExistException e)
|
||||
catch (SiteDoesNotExistException e)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, siteId);
|
||||
}
|
||||
}
|
||||
else if(target instanceof DocumentTarget)
|
||||
else if (target instanceof DocumentTarget)
|
||||
{
|
||||
DocumentTarget documentTarget = (DocumentTarget)target;
|
||||
DocumentTarget documentTarget = (DocumentTarget) target;
|
||||
NodeRef nodeRef = documentTarget.getFile().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||
if (!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
@@ -285,11 +285,11 @@ public class FavouritesImpl implements Favourites
|
||||
PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef);
|
||||
ret = getFavourite(personFavourite, parameters);
|
||||
}
|
||||
else if(target instanceof FolderTarget)
|
||||
else if (target instanceof FolderTarget)
|
||||
{
|
||||
FolderTarget folderTarget = (FolderTarget)target;
|
||||
FolderTarget folderTarget = (FolderTarget) target;
|
||||
NodeRef nodeRef = folderTarget.getFolder().getGuid();
|
||||
if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE)))
|
||||
if (!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE)))
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, nodeRef.getId());
|
||||
}
|
||||
@@ -309,25 +309,25 @@ public class FavouritesImpl implements Favourites
|
||||
boolean exists = false;
|
||||
|
||||
Type type = favouritesService.getType(nodeRef);
|
||||
if(type.equals(Type.SITE))
|
||||
if (type.equals(Type.SITE))
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||
if(siteInfo == null)
|
||||
if (siteInfo == null)
|
||||
{
|
||||
// shouldn't happen because the type implies it's a site
|
||||
throw new AlfrescoRuntimeException("Unable to find site with nodeRef " + nodeRef);
|
||||
}
|
||||
exists = favouritesService.removeFavourite(personId, siteInfo.getNodeRef());
|
||||
}
|
||||
else if(type.equals(Type.FILE))
|
||||
else if (type.equals(Type.FILE))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
else if(type.equals(Type.FOLDER))
|
||||
else if (type.equals(Type.FOLDER))
|
||||
{
|
||||
exists = favouritesService.removeFavourite(personId, nodeRef);
|
||||
}
|
||||
if(!exists)
|
||||
if (!exists)
|
||||
{
|
||||
throw new RelationshipResourceNotFoundException(personId, id);
|
||||
}
|
||||
@@ -347,7 +347,7 @@ public class FavouritesImpl implements Favourites
|
||||
personId = people.validatePerson(personId, true);
|
||||
|
||||
PersonFavourite personFavourite = favouritesService.getFavourite(personId, nodeRef);
|
||||
if(personFavourite != null)
|
||||
if (personFavourite != null)
|
||||
{
|
||||
Favourite favourite = getFavourite(personFavourite, parameters);
|
||||
return favourite;
|
||||
@@ -367,25 +367,26 @@ public class FavouritesImpl implements Favourites
|
||||
|
||||
List<Pair<FavouritesService.SortFields, Boolean>> sortProps = getSortProps(parameters);
|
||||
|
||||
final Set<Type> filteredByClientQuery = new HashSet<Type>();
|
||||
Set<Type> filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; //Default all
|
||||
final Set<Type> filteredByClientQuery = new HashSet<>();
|
||||
Set<Type> filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; // Default all
|
||||
|
||||
// filterType is of the form 'target.<site|file|folder>'
|
||||
QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter()
|
||||
{
|
||||
QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter() {
|
||||
@Override
|
||||
public void or() {
|
||||
//OR is supported but exists() will be called for each EXISTS so we don't
|
||||
//need to do anything here. If we don't override it then it will be assumed
|
||||
//that OR in the grammar is not supported.
|
||||
public void or()
|
||||
{
|
||||
// OR is supported but exists() will be called for each EXISTS so we don't
|
||||
// need to do anything here. If we don't override it then it will be assumed
|
||||
// that OR in the grammar is not supported.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(String filteredByClient, boolean negated) {
|
||||
if(filteredByClient != null)
|
||||
public void exists(String filteredByClient, boolean negated)
|
||||
{
|
||||
int idx = filteredByClient.lastIndexOf("/");
|
||||
if(idx == -1 || idx == filteredByClient.length())
|
||||
if (filteredByClient != null)
|
||||
{
|
||||
int idx = filteredByClient.lastIndexOf('/');
|
||||
if (idx == -1 || idx == filteredByClient.length())
|
||||
{
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
@@ -399,7 +400,7 @@ public class FavouritesImpl implements Favourites
|
||||
}
|
||||
});
|
||||
|
||||
if (filteredByClientQuery.size() > 0)
|
||||
if (!filteredByClientQuery.isEmpty())
|
||||
{
|
||||
filterTypes = filteredByClientQuery;
|
||||
}
|
||||
@@ -419,8 +420,7 @@ public class FavouritesImpl implements Favourites
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code {@link Parameters} object where almost all of its values are null.
|
||||
* the non-null value is the {@literal include} and whatever value is passed for {@code personId} and {@code favouriteId}
|
||||
* Returns a {@code {@link Parameters} object where almost all of its values are null. the non-null value is the {@literal include} and whatever value is passed for {@code personId} and {@code favouriteId}
|
||||
*/
|
||||
private Parameters getDefaultParameters(String personId, String favouriteId)
|
||||
{
|
||||
@@ -434,7 +434,7 @@ public class FavouritesImpl implements Favourites
|
||||
{
|
||||
List<Pair<FavouritesService.SortFields, Boolean>> sortProps = new ArrayList<>();
|
||||
List<SortColumn> sortCols = parameters.getSorting();
|
||||
if ((sortCols != null) && (sortCols.size() > 0))
|
||||
if (sortCols != null && !sortCols.isEmpty())
|
||||
{
|
||||
for (SortColumn sortCol : sortCols)
|
||||
{
|
||||
@@ -447,7 +447,7 @@ public class FavouritesImpl implements Favourites
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
|
||||
}
|
||||
sortProps.add(new Pair<>(sortField, (sortCol.asc ? Boolean.TRUE : Boolean.FALSE)));
|
||||
sortProps.add(new Pair<>(sortField, sortCol.asc ? Boolean.TRUE : Boolean.FALSE));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A document target favourite.
|
||||
*
|
||||
@@ -62,4 +64,24 @@ public class DocumentTarget extends Target
|
||||
return "DocumentTarget [file=" + file + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DocumentTarget that = (DocumentTarget) o;
|
||||
return Objects.equals(file, that.file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(file);
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ package org.alfresco.rest.api.model;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.rest.framework.resource.UniqueId;
|
||||
|
||||
@@ -43,6 +44,7 @@ public class Favourite
|
||||
private Date createdAt;
|
||||
private Target target;
|
||||
private Map<String, Object> properties;
|
||||
private List<String> aspectNames;
|
||||
private List<String> allowableOperations;
|
||||
|
||||
public Date getCreatedAt()
|
||||
@@ -55,7 +57,7 @@ public class Favourite
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
@UniqueId(name="targetGuid")
|
||||
@UniqueId(name = "targetGuid")
|
||||
public String getTargetGuid()
|
||||
{
|
||||
return targetGuid;
|
||||
@@ -86,18 +88,57 @@ public class Favourite
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public List<String> getAllowableOperations() {
|
||||
public List<String> getAspectNames()
|
||||
{
|
||||
return aspectNames;
|
||||
}
|
||||
|
||||
public void setAspectNames(List<String> aspectNames)
|
||||
{
|
||||
this.aspectNames = aspectNames;
|
||||
}
|
||||
|
||||
public List<String> getAllowableOperations()
|
||||
{
|
||||
return allowableOperations;
|
||||
}
|
||||
|
||||
public void setAllowableOperations(List<String> allowableOperations) {
|
||||
public void setAllowableOperations(List<String> allowableOperations)
|
||||
{
|
||||
this.allowableOperations = allowableOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Favourite [targetGuid=" + targetGuid
|
||||
+ ", createdAt=" + createdAt + ", target=" + target + ", properties=" + properties + "]";
|
||||
return "Favourite{" +
|
||||
"targetGuid='" + targetGuid + '\'' +
|
||||
", createdAt=" + createdAt +
|
||||
", target=" + target +
|
||||
", properties=" + properties +
|
||||
", aspectNames=" + aspectNames +
|
||||
", allowableOperations=" + allowableOperations +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Favourite favourite = (Favourite) o;
|
||||
return Objects.equals(targetGuid, favourite.targetGuid) && Objects.equals(createdAt, favourite.createdAt) && Objects.equals(target, favourite.target) && Objects.equals(properties, favourite.properties) && Objects.equals(aspectNames, favourite.aspectNames) && Objects.equals(allowableOperations, favourite.allowableOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(targetGuid, createdAt, target, properties, aspectNames, allowableOperations);
|
||||
}
|
||||
}
|
||||
|
@@ -25,18 +25,17 @@
|
||||
*/
|
||||
package org.alfresco;
|
||||
|
||||
import org.alfresco.repo.web.scripts.TestWebScriptRepoServer;
|
||||
import org.alfresco.util.testing.category.DBTests;
|
||||
import org.alfresco.util.testing.category.NonBuildTests;
|
||||
import org.junit.experimental.categories.Categories;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
import org.alfresco.repo.web.scripts.TestWebScriptRepoServer;
|
||||
import org.alfresco.util.testing.category.DBTests;
|
||||
import org.alfresco.util.testing.category.NonBuildTests;
|
||||
|
||||
@RunWith(Categories.class)
|
||||
@Categories.ExcludeCategory({DBTests.class, NonBuildTests.class})
|
||||
@Suite.SuiteClasses({
|
||||
// [classpath:alfresco/application-context.xml, classpath:alfresco/web-scripts-application-context-test.xml,
|
||||
// classpath:alfresco/web-scripts-application-context.xml]
|
||||
org.alfresco.repo.web.scripts.quickshare.QuickShareRestApiTest.class,
|
||||
org.alfresco.repo.web.scripts.admin.AdminWebScriptTest.class,
|
||||
org.alfresco.repo.web.scripts.audit.AuditWebScriptTest.class,
|
||||
@@ -77,6 +76,7 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.repo.web.scripts.node.NodeWebScripTest.class,
|
||||
org.alfresco.rest.api.impl.CommentsImplUnitTest.class,
|
||||
org.alfresco.rest.api.impl.DownloadsImplCheckArchiveStatusUnitTest.class,
|
||||
org.alfresco.rest.api.impl.FavouritesImplUnitTest.class,
|
||||
org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class
|
||||
})
|
||||
public class AppContext04TestSuite
|
||||
|
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.openMocks;
|
||||
|
||||
import static org.alfresco.model.ContentModel.TYPE_CONTENT;
|
||||
import static org.alfresco.service.cmr.favourites.FavouritesService.Type.FILE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import org.alfresco.repo.favourites.PersonFavourite;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
import org.alfresco.rest.api.model.DocumentTarget;
|
||||
import org.alfresco.rest.api.model.Favourite;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.favourites.FavouritesService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link FavouritesImpl} class.
|
||||
*/
|
||||
public class FavouritesImplUnitTest
|
||||
{
|
||||
static final String NODE_ID = "12345678";
|
||||
static final NodeRef NODE_REF = new NodeRef("favourite://node/" + NODE_ID);
|
||||
static final String PERSON_ID = "personId";
|
||||
static final String ASPECT_NAME = "some:aspect";
|
||||
|
||||
@InjectMocks
|
||||
FavouritesImpl favouritesImpl;
|
||||
@Mock
|
||||
People people;
|
||||
@Mock
|
||||
Nodes nodes;
|
||||
@Mock
|
||||
FavouritesService favouritesService;
|
||||
@Mock
|
||||
NamespaceService namespaceService;
|
||||
@Mock
|
||||
Favourite favourite;
|
||||
@Mock
|
||||
Document document;
|
||||
@Mock
|
||||
PersonFavourite personFavourite;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
openMocks(this);
|
||||
|
||||
when(nodes.getDocument(NODE_REF)).thenReturn(document);
|
||||
when(nodes.nodeMatches(NODE_REF, singleton(TYPE_CONTENT), null)).thenReturn(true);
|
||||
when(document.getGuid()).thenReturn(NODE_REF);
|
||||
when(people.validatePerson(PERSON_ID, true)).thenReturn(PERSON_ID);
|
||||
when(personFavourite.getNodeRef()).thenReturn(NODE_REF);
|
||||
when(personFavourite.getType()).thenReturn(FILE);
|
||||
when(favouritesService.addFavourite(PERSON_ID, NODE_REF)).thenReturn(personFavourite);
|
||||
when(namespaceService.getPrefixes(anyString())).thenReturn(List.of("prefix"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFavourite()
|
||||
{
|
||||
DocumentTarget documentTarget = new DocumentTarget(document);
|
||||
when(favourite.getTarget()).thenReturn(documentTarget);
|
||||
|
||||
Favourite response = favouritesImpl.addFavourite(PERSON_ID, favourite);
|
||||
|
||||
Favourite expected = new Favourite();
|
||||
expected.setTarget(documentTarget);
|
||||
expected.setTargetGuid(NODE_ID);
|
||||
assertEquals(expected, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFavouriteIncludeAspectNames()
|
||||
{
|
||||
List<String> includes = List.of("aspectNames");
|
||||
|
||||
DocumentTarget documentTarget = new DocumentTarget(document);
|
||||
when(favourite.getTarget()).thenReturn(documentTarget);
|
||||
when(nodes.getFolderOrDocument(NODE_REF, null, null, includes, null)).thenReturn(document);
|
||||
when(document.getAspectNames()).thenReturn(List.of(ASPECT_NAME));
|
||||
|
||||
Parameters parameters = mock(Parameters.class);
|
||||
when(parameters.getInclude()).thenReturn(includes);
|
||||
|
||||
Favourite response = favouritesImpl.addFavourite(PERSON_ID, favourite, parameters);
|
||||
|
||||
Favourite expected = new Favourite();
|
||||
expected.setTarget(documentTarget);
|
||||
expected.setTargetGuid(NODE_ID);
|
||||
expected.setAspectNames(List.of(ASPECT_NAME));
|
||||
assertEquals(expected, response);
|
||||
}
|
||||
}
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.4.0.37</version>
|
||||
<version>23.4.0.46</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -28,30 +28,26 @@ package org.alfresco.repo.cache.lookup;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Savepoint;
|
||||
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.domain.control.ControlDAO;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
* A cache for two-way lookups of database entities. These are characterized by having a unique
|
||||
* key (perhaps a database ID) and a separate unique key that identifies the object. If no cache
|
||||
* is given, then all calls are passed through to the backing DAO.
|
||||
* A cache for two-way lookups of database entities. These are characterized by having a unique key (perhaps a database ID) and a separate unique key that identifies the object. If no cache is given, then all calls are passed through to the backing DAO.
|
||||
* <p>
|
||||
* The keys must have good <code>equals</code> and <code>hashCode</code> implementations and
|
||||
* must respect the case-sensitivity of the use-case.
|
||||
* The keys must have good <code>equals</code> and <code>hashCode</code> implementations and must respect the case-sensitivity of the use-case.
|
||||
* <p>
|
||||
* All keys will be unique to the given cache region, allowing the cache to be shared
|
||||
* between instances of this class.
|
||||
* All keys will be unique to the given cache region, allowing the cache to be shared between instances of this class.
|
||||
* <p>
|
||||
* Generics:
|
||||
* <ul>
|
||||
* <li>K: The database unique identifier.</li>
|
||||
* <li>V: The value stored against K.</li>
|
||||
* <li>VK: The a value-derived key that will be used as a cache key when caching K for lookups by V.
|
||||
* This can be the value itself if it is itself a good key.</li>
|
||||
* <li>VK: The a value-derived key that will be used as a cache key when caching K for lookups by V. This can be the value itself if it is itself a good key.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
@@ -65,60 +61,47 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
public static interface EntityLookupCallbackDAO<K1 extends Serializable, V1 extends Object, VK1 extends Serializable>
|
||||
{
|
||||
/**
|
||||
* Resolve the given value into a unique value key that can be used to find the entity's ID.
|
||||
* A return value should be small and efficient; don't return a value if this is not possible.
|
||||
* Resolve the given value into a unique value key that can be used to find the entity's ID. A return value should be small and efficient; don't return a value if this is not possible.
|
||||
* <p/>
|
||||
* Implementations will often return the value itself, provided that the value is both
|
||||
* serializable and has a good <code>equals</code> and <code>hashCode</code>.
|
||||
* Implementations will often return the value itself, provided that the value is both serializable and has a good <code>equals</code> and <code>hashCode</code>.
|
||||
* <p/>
|
||||
* Were no adequate key can be generated for the value, then <tt>null</tt> can be returned.
|
||||
* In this case, the {@link #findByValue(Object) findByValue} method might not even do a search
|
||||
* and just return <tt>null</tt> itself i.e. if it is difficult to look the value up in storage
|
||||
* then it is probably difficult to generate a cache key from it, too.. In this scenario, the
|
||||
* cache will be purely for key-based lookups
|
||||
* Were no adequate key can be generated for the value, then <tt>null</tt> can be returned. In this case, the {@link #findByValue(Object) findByValue} method might not even do a search and just return <tt>null</tt> itself i.e. if it is difficult to look the value up in storage then it is probably difficult to generate a cache key from it, too.. In this scenario, the cache will be purely for key-based lookups
|
||||
*
|
||||
* @param value the full value being keyed (never <tt>null</tt>)
|
||||
* @return Returns the business key representing the entity, or <tt>null</tt>
|
||||
* if an economical key cannot be generated.
|
||||
* @param value
|
||||
* the full value being keyed (never <tt>null</tt>)
|
||||
* @return Returns the business key representing the entity, or <tt>null</tt> if an economical key cannot be generated.
|
||||
*/
|
||||
VK1 getValueKey(V1 value);
|
||||
|
||||
/**
|
||||
* Find an entity for a given key.
|
||||
*
|
||||
* @param key the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @param key
|
||||
* the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @return Return the entity or <tt>null</tt> if no entity is exists for the ID
|
||||
*/
|
||||
Pair<K1, V1> findByKey(K1 key);
|
||||
|
||||
/**
|
||||
* Find and entity using the given value key. The <code>equals</code> and <code>hashCode</code>
|
||||
* methods of the value object should respect case-sensitivity in the same way that this
|
||||
* lookup treats case-sensitivity i.e. if the <code>equals</code> method is <b>case-sensitive</b>
|
||||
* then this method should look the entity up using a <b>case-sensitive</b> search.
|
||||
* Find and entity using the given value key. The <code>equals</code> and <code>hashCode</code> methods of the value object should respect case-sensitivity in the same way that this lookup treats case-sensitivity i.e. if the <code>equals</code> method is <b>case-sensitive</b> then this method should look the entity up using a <b>case-sensitive</b> search.
|
||||
* <p/>
|
||||
* Since this is a cache backed by some sort of database, <tt>null</tt> values are allowed by the
|
||||
* cache. The implementation of this method can throw an exception if <tt>null</tt> is not
|
||||
* appropriate for the use-case.
|
||||
* Since this is a cache backed by some sort of database, <tt>null</tt> values are allowed by the cache. The implementation of this method can throw an exception if <tt>null</tt> is not appropriate for the use-case.
|
||||
* <p/>
|
||||
* If the search is impossible or expensive, this method should just return <tt>null</tt>. This
|
||||
* would usually be the case if the {@link #getValueKey(Object) getValueKey} method also returned
|
||||
* <tt>null</tt> i.e. if it is difficult to look the value up in storage then it is probably
|
||||
* difficult to generate a cache key from it, too.
|
||||
* If the search is impossible or expensive, this method should just return <tt>null</tt>. This would usually be the case if the {@link #getValueKey(Object) getValueKey} method also returned <tt>null</tt> i.e. if it is difficult to look the value up in storage then it is probably difficult to generate a cache key from it, too.
|
||||
*
|
||||
* @param value the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||
* @param value
|
||||
* the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||
* @return Return the entity or <tt>null</tt> if no entity matches the given value
|
||||
*/
|
||||
Pair<K1, V1> findByValue(V1 value);
|
||||
|
||||
/**
|
||||
* Create an entity using the given values. It is valid to assume that the entity does not exist
|
||||
* within the current transaction at least.
|
||||
* Create an entity using the given values. It is valid to assume that the entity does not exist within the current transaction at least.
|
||||
* <p/>
|
||||
* Since persistence mechanisms often allow <tt>null</tt> values, these can be expected here. The
|
||||
* implementation must throw an exception if <tt>null</tt> is not allowed for the specific use-case.
|
||||
* Since persistence mechanisms often allow <tt>null</tt> values, these can be expected here. The implementation must throw an exception if <tt>null</tt> is not allowed for the specific use-case.
|
||||
*
|
||||
* @param value the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||
* @param value
|
||||
* the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||
* @return Return the newly-created entity ID-value pair
|
||||
*/
|
||||
Pair<K1, V1> createValue(V1 value);
|
||||
@@ -126,44 +109,47 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Update the entity identified by the given key.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||
*
|
||||
* @param key the existing key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @param value the new value
|
||||
* @param key
|
||||
* the existing key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @param value
|
||||
* the new value
|
||||
* @return Returns the row update count.
|
||||
* @throws UnsupportedOperationException if entity updates are not supported
|
||||
* @throws UnsupportedOperationException
|
||||
* if entity updates are not supported
|
||||
*/
|
||||
int updateValue(K1 key, V1 value);
|
||||
|
||||
/**
|
||||
* Delete an entity for the given key.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||
*
|
||||
* @param key the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @param key
|
||||
* the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||
* @return Returns the row deletion count.
|
||||
* @throws UnsupportedOperationException if entity deletion is not supported
|
||||
* @throws UnsupportedOperationException
|
||||
* if entity deletion is not supported
|
||||
*/
|
||||
int deleteByKey(K1 key);
|
||||
|
||||
/**
|
||||
* Delete an entity for the given value.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||
*
|
||||
* @param value the value (business object) used to identify the enitity (<tt>null</tt> allowed)
|
||||
* @param value
|
||||
* the value (business object) used to identify the enitity (<tt>null</tt> allowed)
|
||||
* @return Returns the row deletion count.
|
||||
* @throws UnsupportedOperationException if entity deletion is not supported
|
||||
* @throws UnsupportedOperationException
|
||||
* if entity deletion is not supported
|
||||
*/
|
||||
int deleteByValue(V1 value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adaptor for implementations that support immutable entities. The update and delete operations
|
||||
* throw {@link UnsupportedOperationException}.
|
||||
* Adaptor for implementations that support immutable entities. The update and delete operations throw {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.2
|
||||
@@ -194,7 +180,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Disallows the operation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
* @throws UnsupportedOperationException
|
||||
* always
|
||||
*/
|
||||
public int updateValue(K2 key, V2 value)
|
||||
{
|
||||
@@ -204,7 +191,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Disallows the operation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
* @throws UnsupportedOperationException
|
||||
* always
|
||||
*/
|
||||
public int deleteByKey(K2 key)
|
||||
{
|
||||
@@ -214,7 +202,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Disallows the operation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
* @throws UnsupportedOperationException
|
||||
* always
|
||||
*/
|
||||
public int deleteByValue(V2 value)
|
||||
{
|
||||
@@ -240,10 +229,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
private final String cacheRegion;
|
||||
|
||||
/**
|
||||
* Construct the lookup cache <b>without any cache</b>. All calls are passed directly to the
|
||||
* underlying DAO entity lookup.
|
||||
* Construct the lookup cache <b>without any cache</b>. All calls are passed directly to the underlying DAO entity lookup.
|
||||
*
|
||||
* @param entityLookup the instance that is able to find and persist entities
|
||||
* @param entityLookup
|
||||
* the instance that is able to find and persist entities
|
||||
*/
|
||||
public EntityLookupCache(EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||
{
|
||||
@@ -253,8 +242,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Construct the lookup cache, using the {@link #CACHE_REGION_DEFAULT default cache region}.
|
||||
*
|
||||
* @param cache the cache that will back the two-way lookups
|
||||
* @param entityLookup the instance that is able to find and persist entities
|
||||
* @param cache
|
||||
* the cache that will back the two-way lookups
|
||||
* @param entityLookup
|
||||
* the instance that is able to find and persist entities
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public EntityLookupCache(SimpleCache cache, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||
@@ -265,15 +256,16 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Construct the lookup cache, using the given cache region.
|
||||
* <p>
|
||||
* All keys will be unique to the given cache region, allowing the cache to be shared
|
||||
* between instances of this class.
|
||||
* All keys will be unique to the given cache region, allowing the cache to be shared between instances of this class.
|
||||
*
|
||||
* @param cache the cache that will back the two-way lookups; <tt>null</tt> to have no backing
|
||||
* in a cache.
|
||||
* @param cacheRegion the region within the cache to use.
|
||||
* @param entityLookup the instance that is able to find and persist entities
|
||||
* @param cache
|
||||
* the cache that will back the two-way lookups; <tt>null</tt> to have no backing in a cache.
|
||||
* @param cacheRegion
|
||||
* the region within the cache to use.
|
||||
* @param entityLookup
|
||||
* the instance that is able to find and persist entities
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public EntityLookupCache(SimpleCache cache, String cacheRegion, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||
{
|
||||
ParameterCheck.mandatory("cacheRegion", cacheRegion);
|
||||
@@ -284,14 +276,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity associated with the given key.
|
||||
* The {@link EntityLookupCallbackDAO#findByKey(Serializable) entity callback} will be used if necessary.
|
||||
* Find the entity associated with the given key. The {@link EntityLookupCallbackDAO#findByKey(Serializable) entity callback} will be used if necessary.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation
|
||||
* or not; the former would normally result in a concurrency-related exception such as
|
||||
* {@link ConcurrencyFailureException}.
|
||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation or not; the former would normally result in a concurrency-related exception such as {@link ConcurrencyFailureException}.
|
||||
*
|
||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param key
|
||||
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @return Returns the key-value pair or <tt>null</tt> if the key doesn't reference an entity
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -337,7 +327,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
{
|
||||
value = entityPair.getSecond();
|
||||
// Get the value key
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
// Check if the value has a good key
|
||||
if (valueKey != null)
|
||||
{
|
||||
@@ -354,14 +344,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity associated with the given value.
|
||||
* The {@link EntityLookupCallbackDAO#findByValue(Object) entity callback} will be used if no entry exists in the cache.
|
||||
* Find the entity associated with the given value. The {@link EntityLookupCallbackDAO#findByValue(Object) entity callback} will be used if no entry exists in the cache.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation
|
||||
* or not; the former would normally result in a concurrency-related exception such as
|
||||
* {@link ConcurrencyFailureException}.
|
||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation or not; the former would normally result in a concurrency-related exception such as {@link ConcurrencyFailureException}.
|
||||
*
|
||||
* @param value The entity value, which may be valid or invalid (<tt>null</tt> is allowed)
|
||||
* @param value
|
||||
* The entity value, which may be valid or invalid (<tt>null</tt> is allowed)
|
||||
* @return Returns the key-value pair or <tt>null</tt> if the value doesn't reference an entity
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -376,7 +364,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
// Get the value key.
|
||||
// The cast to (VK) is counter-intuitive, but works because they're all just Serializable
|
||||
// It's nasty, but hidden from the cache client code.
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
// Check if the value has a good key
|
||||
if (valueKey == null)
|
||||
{
|
||||
@@ -423,15 +411,14 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
|
||||
/**
|
||||
* Attempt to create the entity and, failing that, look it up.<br/>
|
||||
* This method takes the opposite approach to {@link #getOrCreateByValue(Object)}, which assumes the entity's
|
||||
* existence: in this case the entity is assumed to NOT exist.
|
||||
* The {@link EntityLookupCallbackDAO#createValue(Object)} and {@link EntityLookupCallbackDAO#findByValue(Object)}
|
||||
* will be used if necessary.<br/>
|
||||
* This method takes the opposite approach to {@link #getOrCreateByValue(Object)}, which assumes the entity's existence: in this case the entity is assumed to NOT exist. The {@link EntityLookupCallbackDAO#createValue(Object)} and {@link EntityLookupCallbackDAO#findByValue(Object)} will be used if necessary.<br/>
|
||||
* <p/>
|
||||
* Use this method when the data involved is seldom reused.
|
||||
*
|
||||
* @param value The entity value (<tt>null</tt> is allowed)
|
||||
* @param controlDAO an essential DAO required in order to ensure a transactionally-safe attempt at data creation
|
||||
* @param value
|
||||
* The entity value (<tt>null</tt> is allowed)
|
||||
* @param controlDAO
|
||||
* an essential DAO required in order to ensure a transactionally-safe attempt at data creation
|
||||
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
||||
*/
|
||||
public Pair<K, V> createOrGetByValue(V value, ControlDAO controlDAO)
|
||||
@@ -448,6 +435,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
// Cache it
|
||||
if (cache != null)
|
||||
{
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
cache.put(new CacheRegionValueKey(cacheRegion, valueKey), entityPair.getFirst());
|
||||
cache.put(
|
||||
new CacheRegionKey(cacheRegion, entityPair.getFirst()),
|
||||
(entityPair.getSecond() == null ? VALUE_NULL : entityPair.getSecond()));
|
||||
@@ -464,11 +453,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity associated with the given value and create it if it doesn't exist.
|
||||
* The {@link EntityLookupCallbackDAO#findByValue(Object)} and {@link EntityLookupCallbackDAO#createValue(Object)}
|
||||
* will be used if necessary.
|
||||
* Find the entity associated with the given value and create it if it doesn't exist. The {@link EntityLookupCallbackDAO#findByValue(Object)} and {@link EntityLookupCallbackDAO#createValue(Object)} will be used if necessary.
|
||||
*
|
||||
* @param value The entity value (<tt>null</tt> is allowed)
|
||||
* @param value
|
||||
* The entity value (<tt>null</tt> is allowed)
|
||||
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -488,7 +476,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
// Get the value key
|
||||
// The cast to (VK) is counter-intuitive, but works because they're all just Serializable.
|
||||
// It's nasty, but hidden from the cache client code.
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
// Check if the value has a good key
|
||||
if (valueKey == null)
|
||||
{
|
||||
@@ -530,16 +518,14 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the entity associated with the given key.
|
||||
* The {@link EntityLookupCallbackDAO#updateValue(Serializable, Object)} callback
|
||||
* will be used if necessary.
|
||||
* Update the entity associated with the given key. The {@link EntityLookupCallbackDAO#updateValue(Serializable, Object)} callback will be used if necessary.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
*
|
||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param value The new entity value (may be <tt>null</tt>)
|
||||
* @param key
|
||||
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param value
|
||||
* The new entity value (may be <tt>null</tt>)
|
||||
* @return Returns the row update count.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -564,7 +550,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
// Get the value key.
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
// Check if the value has a good key
|
||||
if (valueKey != null)
|
||||
{
|
||||
@@ -580,10 +566,44 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity associated with the given value if its cached
|
||||
*
|
||||
* @param value
|
||||
* The entity value (<tt>null</tt> is not allowed)
|
||||
* @return Returns the key-value pair (existing or <tt>null</tt>)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Pair<K, V> getCachedEntityByValue(V value)
|
||||
{
|
||||
if (cache == null || value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
VK valueKey = entityLookup.getValueKey(value);
|
||||
if (valueKey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve the cached value
|
||||
CacheRegionValueKey valueCacheKey = new CacheRegionValueKey(cacheRegion, valueKey);
|
||||
K key = (K) cache.get(valueCacheKey);
|
||||
|
||||
if (key != null && !key.equals(VALUE_NOT_FOUND))
|
||||
{
|
||||
return getByKey(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache-only operation: Get the key for a given value key (note: not 'value' but 'value key').
|
||||
*
|
||||
* @param valueKey The entity value key, which must be valid (<tt>null</tt> not allowed)
|
||||
* @param valueKey
|
||||
* The entity value key, which must be valid (<tt>null</tt> not allowed)
|
||||
* @return The entity key (may be <tt>null</tt>)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -603,7 +623,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Cache-only operation: Get the value for a given key
|
||||
*
|
||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param key
|
||||
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @return The entity value (may be <tt>null</tt>)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -634,8 +655,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Cache-only operation: Update the cache's value
|
||||
*
|
||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param value The new entity value (may be <tt>null</tt>)
|
||||
* @param key
|
||||
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param value
|
||||
* The new entity value (may be <tt>null</tt>)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setValue(K key, V value)
|
||||
@@ -651,7 +674,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
removeByKey(key, false);
|
||||
|
||||
// Get the value key.
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
// Check if the value has a good key
|
||||
if (valueKey != null)
|
||||
{
|
||||
@@ -667,14 +690,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the entity associated with the given key.
|
||||
* The {@link EntityLookupCallbackDAO#deleteByKey(Serializable)} callback will be used if necessary.
|
||||
* Delete the entity associated with the given key. The {@link EntityLookupCallbackDAO#deleteByKey(Serializable)} callback will be used if necessary.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
*
|
||||
* @param key the entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @param key
|
||||
* the entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||
* @return Returns the row deletion count
|
||||
*/
|
||||
public int deleteByKey(K key)
|
||||
@@ -693,14 +714,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the entity having the given value..
|
||||
* The {@link EntityLookupCallbackDAO#deleteByValue(Object)} callback will be used if necessary.
|
||||
* Delete the entity having the given value.. The {@link EntityLookupCallbackDAO#deleteByValue(Object)} callback will be used if necessary.
|
||||
* <p/>
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||
*
|
||||
* @param value the entity value, which may be valid or invalid (<tt>null</tt> allowed)
|
||||
* @param value
|
||||
* the entity value, which may be valid or invalid (<tt>null</tt> allowed)
|
||||
* @return Returns the row deletion count
|
||||
*/
|
||||
public int deleteByValue(V value)
|
||||
@@ -735,7 +754,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Cache-only operation: Remove all cache values associated with the given key.
|
||||
*
|
||||
* @param removeKey <tt>true</tt> to remove the given key's entry
|
||||
* @param removeKey
|
||||
* <tt>true</tt> to remove the given key's entry
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void removeByKey(K key, boolean removeKey)
|
||||
@@ -761,7 +781,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
/**
|
||||
* Cache-only operation: Remove all cache values associated with the given value
|
||||
*
|
||||
* @param value The entity value (<tt>null</tt> is allowed)
|
||||
* @param value
|
||||
* The entity value (<tt>null</tt> is allowed)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void removeByValue(V value)
|
||||
@@ -773,7 +794,7 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
||||
}
|
||||
|
||||
// Get the value key
|
||||
VK valueKey = (value == null) ? (VK)VALUE_NULL : entityLookup.getValueKey(value);
|
||||
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||
if (valueKey == null)
|
||||
{
|
||||
// No key generated for the value. There is nothing that can be done.
|
||||
|
@@ -31,6 +31,11 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
||||
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
|
||||
@@ -45,19 +50,13 @@ import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.transaction.TransactionListenerAdapter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
/**
|
||||
* Abstract implementation for ContentData DAO.
|
||||
* <p>
|
||||
* This provides basic services such as caching, but defers to the underlying implementation
|
||||
* for CRUD operations.
|
||||
* This provides basic services such as caching, but defers to the underlying implementation for CRUD operations.
|
||||
* <p>
|
||||
* The DAO deals in {@link ContentData} instances. The cache is primarily present to decode
|
||||
* IDs into <code>ContentData</code> instances.
|
||||
* The DAO deals in {@link ContentData} instances. The cache is primarily present to decode IDs into <code>ContentData</code> instances.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author sglover
|
||||
@@ -127,7 +126,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
/**
|
||||
* Set this property to enable eager cleanup of orphaned content.
|
||||
*
|
||||
* @param contentStoreCleaner an eager cleaner (may be <tt>null</tt>)
|
||||
* @param contentStoreCleaner
|
||||
* an eager cleaner (may be <tt>null</tt>)
|
||||
*/
|
||||
public void setContentStoreCleaner(EagerContentStoreCleaner contentStoreCleaner)
|
||||
{
|
||||
@@ -135,7 +135,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentDataCache the cache of IDs to ContentData and vice versa
|
||||
* @param contentDataCache
|
||||
* the cache of IDs to ContentData and vice versa
|
||||
*/
|
||||
public void setContentDataCache(SimpleCache<Long, ContentData> contentDataCache)
|
||||
{
|
||||
@@ -154,8 +155,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
}
|
||||
|
||||
/**
|
||||
* A <b>content_url</b> entity was dereferenced. This makes no assumptions about the
|
||||
* current references - dereference deletion is handled in the commit phase.
|
||||
* A <b>content_url</b> entity was dereferenced. This makes no assumptions about the current references - dereference deletion is handled in the commit phase.
|
||||
*/
|
||||
protected void registerDereferencedContentUrl(String contentUrl)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
throw new IllegalArgumentException("Cannot look up ContentData by null ID.");
|
||||
}
|
||||
Pair<Long, ContentUrlEntity> pair = contentUrlCache.getByValue(contentUrl);
|
||||
if(pair != null)
|
||||
if (pair != null)
|
||||
{
|
||||
result = contentUrlCache.updateValue(pair.getFirst(), contentUrl);
|
||||
}
|
||||
@@ -413,7 +413,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
// Decode content URL
|
||||
Long contentUrlId = contentDataEntity.getContentUrlId();
|
||||
String contentUrl = null;
|
||||
if(contentUrlId != null)
|
||||
if (contentUrlId != null)
|
||||
{
|
||||
Pair<Long, ContentUrlEntity> entityPair = contentUrlCache.getByKey(contentUrlId);
|
||||
if (entityPair == null)
|
||||
@@ -470,7 +470,15 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
|
||||
contentUrlEntity.setContentUrl(contentUrl);
|
||||
contentUrlEntity.setSize(size);
|
||||
Pair<Long, ContentUrlEntity> pair = contentUrlCache.createOrGetByValue(contentUrlEntity, controlDAO);
|
||||
|
||||
// Attempt to get the data from cache
|
||||
Pair<Long, ContentUrlEntity> pair = contentUrlCache.getCachedEntityByValue(contentUrlEntity);
|
||||
|
||||
if (pair == null)
|
||||
{
|
||||
pair = contentUrlCache.createOrGetByValue(contentUrlEntity, controlDAO);
|
||||
}
|
||||
|
||||
contentUrlId = pair.getFirst();
|
||||
}
|
||||
|
||||
@@ -510,7 +518,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
// Resolve the content URL
|
||||
Long oldContentUrlId = contentDataEntity.getContentUrlId();
|
||||
ContentUrlEntity contentUrlEntity = null;
|
||||
if(oldContentUrlId != null)
|
||||
if (oldContentUrlId != null)
|
||||
{
|
||||
Pair<Long, ContentUrlEntity> entityPair = contentUrlCache.getByKey(oldContentUrlId);
|
||||
if (entityPair == null)
|
||||
@@ -531,7 +539,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
}
|
||||
if (newContentUrl != null)
|
||||
{
|
||||
if(contentUrlEntity == null)
|
||||
if (contentUrlEntity == null)
|
||||
{
|
||||
contentUrlEntity = new ContentUrlEntity();
|
||||
contentUrlEntity.setContentUrl(newContentUrl);
|
||||
@@ -595,7 +603,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
boolean success = true;
|
||||
|
||||
ContentUrlEntity existing = getContentUrl(contentUrlId);
|
||||
if(existing != null)
|
||||
if (existing != null)
|
||||
{
|
||||
ContentUrlEntity entity = ContentUrlEntity.setContentUrlKey(existing, contentUrlKey);
|
||||
updateContentUrl(entity);
|
||||
@@ -638,32 +646,36 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentUrl the content URL to create or search for
|
||||
* @param contentUrl
|
||||
* the content URL to create or search for
|
||||
*/
|
||||
protected abstract ContentUrlEntity createContentUrlEntity(String contentUrl, long size, ContentUrlKeyEntity contentUrlKey);
|
||||
|
||||
/**
|
||||
* @param id the ID of the <b>content url</b> entity
|
||||
* @param id
|
||||
* the ID of the <b>content url</b> entity
|
||||
* @return Return the entity or <tt>null</tt> if it doesn't exist
|
||||
*/
|
||||
protected abstract ContentUrlEntity getContentUrlEntity(Long id);
|
||||
|
||||
protected abstract ContentUrlEntity getContentUrlEntity(String contentUrl);
|
||||
|
||||
|
||||
/**
|
||||
* @param contentUrl the URL of the <b>content url</b> entity
|
||||
* @return Return the entity or <tt>null</tt> if it doesn't exist or is still
|
||||
* referenced by a <b>content_data</b> entity
|
||||
* @param contentUrl
|
||||
* the URL of the <b>content url</b> entity
|
||||
* @return Return the entity or <tt>null</tt> if it doesn't exist or is still referenced by a <b>content_data</b> entity
|
||||
*/
|
||||
protected abstract ContentUrlEntity getContentUrlEntityUnreferenced(String contentUrl);
|
||||
|
||||
/**
|
||||
* Update a content URL with the given orphan time
|
||||
*
|
||||
* @param id the unique ID of the entity
|
||||
* @param orphanTime the time (ms since epoch) that the entity was orphaned
|
||||
* @param oldOrphanTime the orphan time we expect to update for optimistic locking (may be <tt>null</tt>)
|
||||
* @param id
|
||||
* the unique ID of the entity
|
||||
* @param orphanTime
|
||||
* the time (ms since epoch) that the entity was orphaned
|
||||
* @param oldOrphanTime
|
||||
* the orphan time we expect to update for optimistic locking (may be <tt>null</tt>)
|
||||
* @return Returns the number of rows updated
|
||||
*/
|
||||
protected abstract int updateContentUrlOrphanTime(Long id, Long orphanTime, Long oldOrphanTime);
|
||||
@@ -678,13 +690,15 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
Long localeId);
|
||||
|
||||
/**
|
||||
* @param id the entity ID
|
||||
* @param id
|
||||
* the entity ID
|
||||
* @return Returns the entity or <tt>null</tt> if it doesn't exist
|
||||
*/
|
||||
protected abstract ContentDataEntity getContentDataEntity(Long id);
|
||||
|
||||
/**
|
||||
* @param nodeIds the node ID
|
||||
* @param nodeIds
|
||||
* the node ID
|
||||
* @return Returns the associated entities or <tt>null</tt> if none exist
|
||||
*/
|
||||
protected abstract List<ContentDataEntity> getContentDataEntitiesForNodes(Set<Long> nodeIds);
|
||||
@@ -692,7 +706,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
/**
|
||||
* Update an existing <b>alf_content_data</b> entity
|
||||
*
|
||||
* @param entity the existing entity that will be updated
|
||||
* @param entity
|
||||
* the existing entity that will be updated
|
||||
* @return Returns the number of rows updated (should be 1)
|
||||
*/
|
||||
protected abstract int updateContentDataEntity(ContentDataEntity entity);
|
||||
@@ -705,6 +720,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
||||
protected abstract int deleteContentDataEntity(Long id);
|
||||
|
||||
protected abstract int deleteContentUrlEntity(long id);
|
||||
|
||||
protected abstract int updateContentUrlEntity(ContentUrlEntity existing, ContentUrlEntity entity);
|
||||
|
||||
/**
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -28,13 +28,11 @@ package org.alfresco.repo.security.permissions;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
|
||||
/**
|
||||
* Interface for collection-based results that describe permission filtering
|
||||
* behaviour around cut-off limits.
|
||||
* Interface for collection-based results that describe permission filtering behaviour around cut-off limits.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
@@ -42,16 +40,15 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
public interface PermissionCheckCollection<T>
|
||||
{
|
||||
/**
|
||||
* Get the desired number of results. Permission checks can stop once the number of
|
||||
* return objects reaches this number.
|
||||
* Get the desired number of results. Permission checks can stop once the number of return objects reaches this number.
|
||||
*
|
||||
* @return the number of results desired
|
||||
*/
|
||||
int getTargetResultCount();
|
||||
|
||||
/**
|
||||
* Get the maximum time for permission checks to execute before cutting the results off.
|
||||
* <br/>Zero: Ignore this value.
|
||||
* Get the maximum time for permission checks to execute before cutting the results off. <br/>
|
||||
* Zero: Ignore this value.
|
||||
*
|
||||
* @return the time allowed for permission checks before cutoff
|
||||
*/
|
||||
@@ -65,16 +62,16 @@ public interface PermissionCheckCollection<T>
|
||||
int getCutOffAfterCount();
|
||||
|
||||
/**
|
||||
* Helper 'introduction' to allow simple addition of the {@link PermissionCheckCollection} interface to
|
||||
* existing collections.
|
||||
* Helper 'introduction' to allow simple addition of the {@link PermissionCheckCollection} interface to existing collections.
|
||||
*
|
||||
* @param <T> the type of the <code>Collection</code> in use
|
||||
* @param <T>
|
||||
* the type of the <code>Collection</code> in use
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class PermissionCheckCollectionMixin<T> extends DelegatingIntroductionInterceptor implements PermissionCheckCollection<T>
|
||||
class PermissionCheckCollectionMixin<T> extends DelegatingIntroductionInterceptor implements PermissionCheckCollection<T>
|
||||
{
|
||||
private final int targetResultCount;
|
||||
private final long cutOffAfterTimeMs;
|
||||
@@ -117,18 +114,20 @@ public interface PermissionCheckCollection<T>
|
||||
/**
|
||||
* Helper method to create a {@link PermissionCheckCollection} from an existing <code>Collection</code>
|
||||
*
|
||||
* @param <TT> the type of the <code>Collection</code>
|
||||
* @param collection the <code>Collection</code> to proxy
|
||||
* @param targetResultCount the desired number of results or default to the collection size
|
||||
* @param cutOffAfterTimeMs the number of milliseconds to wait before cut-off or zero to use the system default
|
||||
* time-based cut-off.
|
||||
* @param cutOffAfterCount the number of permission checks to process before cut-off or zero to use the system default
|
||||
* count-based cut-off.
|
||||
* @return a <code>Collection</code> of the same type but including the
|
||||
* {@link PermissionCheckCollection} interface
|
||||
* @param <TT>
|
||||
* the type of the <code>Collection</code>
|
||||
* @param collection
|
||||
* the <code>Collection</code> to proxy
|
||||
* @param targetResultCount
|
||||
* the desired number of results or default to the collection size
|
||||
* @param cutOffAfterTimeMs
|
||||
* the number of milliseconds to wait before cut-off or zero to use the system default time-based cut-off.
|
||||
* @param cutOffAfterCount
|
||||
* the number of permission checks to process before cut-off or zero to use the system default count-based cut-off.
|
||||
* @return a <code>Collection</code> of the same type but including the {@link PermissionCheckCollection} interface
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final <TT> Collection<TT> create(
|
||||
public static <TT> Collection<TT> create(
|
||||
Collection<TT> collection,
|
||||
int targetResultCount, long cutOffAfterTimeMs, int cutOffAfterCount)
|
||||
{
|
||||
@@ -137,19 +136,14 @@ public interface PermissionCheckCollection<T>
|
||||
targetResultCount = collection.size();
|
||||
}
|
||||
// Create the mixin
|
||||
DelegatingIntroductionInterceptor mixin = new PermissionCheckCollectionMixin<Integer>(
|
||||
DelegatingIntroductionInterceptor mixin = new PermissionCheckCollectionMixin<>(
|
||||
targetResultCount,
|
||||
cutOffAfterTimeMs,
|
||||
cutOffAfterCount);
|
||||
// Create the advisor
|
||||
IntroductionAdvisor advisor = new DefaultIntroductionAdvisor(mixin, PermissionCheckCollection.class);
|
||||
// Proxy
|
||||
ProxyFactory pf = new ProxyFactory(collection);
|
||||
pf.addAdvisor(advisor);
|
||||
Object proxiedObject = pf.getProxy();
|
||||
|
||||
// Done
|
||||
return (Collection<TT>) proxiedObject;
|
||||
// Create Proxy
|
||||
return (Collection<TT>) ProxyFactoryUtils.createProxy(collection, advisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -28,13 +28,11 @@ package org.alfresco.repo.security.permissions;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
|
||||
/**
|
||||
* Interface for collection-based results that carry extra information
|
||||
* about the state of permission cut-offs.
|
||||
* Interface for collection-based results that carry extra information about the state of permission cut-offs.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
@@ -44,14 +42,12 @@ public interface PermissionCheckedCollection<T>
|
||||
/**
|
||||
* Check if the results have been truncated by permission check limits.
|
||||
*
|
||||
* @return <tt>true</tt> - if the results (usually a collection) have been
|
||||
* cut off by permission check limits
|
||||
* @return <tt>true</tt> - if the results (usually a collection) have been cut off by permission check limits
|
||||
*/
|
||||
boolean isCutOff();
|
||||
|
||||
/**
|
||||
* Get the number of objects in the original (unfiltered) collection that did
|
||||
* <b>not</b> have any permission checks.
|
||||
* Get the number of objects in the original (unfiltered) collection that did <b>not</b> have any permission checks.
|
||||
*
|
||||
* @return number of entries from the original collection that were not checked
|
||||
*/
|
||||
@@ -65,20 +61,21 @@ public interface PermissionCheckedCollection<T>
|
||||
int sizeOriginal();
|
||||
|
||||
/**
|
||||
* Helper 'introduction' to allow simple addition of the {@link PermissionCheckedCollection} interface to
|
||||
* existing collections.
|
||||
* Helper 'introduction' to allow simple addition of the {@link PermissionCheckedCollection} interface to existing collections.
|
||||
*
|
||||
* @param <T> the type of the <code>Collection</code> in use
|
||||
* @param <T>
|
||||
* the type of the <code>Collection</code> in use
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class PermissionCheckedCollectionMixin<T> extends DelegatingIntroductionInterceptor implements PermissionCheckedCollection<T>
|
||||
class PermissionCheckedCollectionMixin<T> extends DelegatingIntroductionInterceptor implements PermissionCheckedCollection<T>
|
||||
{
|
||||
private final boolean isCutOff;
|
||||
private final int sizeUnchecked;
|
||||
private final int sizeOriginal;
|
||||
|
||||
private PermissionCheckedCollectionMixin(boolean isCutOff, int sizeUnchecked, int sizeOriginal)
|
||||
{
|
||||
super();
|
||||
@@ -86,34 +83,37 @@ public interface PermissionCheckedCollection<T>
|
||||
this.sizeUnchecked = sizeUnchecked;
|
||||
this.sizeOriginal = sizeOriginal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCutOff()
|
||||
{
|
||||
return isCutOff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sizeUnchecked()
|
||||
{
|
||||
return sizeUnchecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sizeOriginal()
|
||||
{
|
||||
return sizeOriginal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a {@link PermissionCheckedCollection} from an existing <code>Collection</code>
|
||||
* by applying the same values as present on a potentially permission-checked source. If the
|
||||
* existing checked source is <b>NOT</b> permission-checked, then the collection will not be
|
||||
* decorated.
|
||||
* Helper method to create a {@link PermissionCheckedCollection} from an existing <code>Collection</code> by applying the same values as present on a potentially permission-checked source. If the existing checked source is <b>NOT</b> permission-checked, then the collection will not be decorated.
|
||||
*
|
||||
* @param <TT> the type of the <code>Collection</code>
|
||||
* @param collection the <code>Collection</code> to proxy
|
||||
* @param checkedSource a collection that might implement {@link PermissionCheckedCollection}
|
||||
* @return a <code>Collection</code> of the same type but including the
|
||||
* {@link PermissionCheckedCollection} interface
|
||||
* @param <TT>
|
||||
* the type of the <code>Collection</code>
|
||||
* @param collection
|
||||
* the <code>Collection</code> to proxy
|
||||
* @param checkedSource
|
||||
* a collection that might implement {@link PermissionCheckedCollection}
|
||||
* @return a <code>Collection</code> of the same type but including the {@link PermissionCheckedCollection} interface
|
||||
*/
|
||||
public static final <TT> Collection<TT> create(
|
||||
public static <TT> Collection<TT> create(
|
||||
Collection<TT> collection, Collection<?> checkedSource)
|
||||
{
|
||||
if (checkedSource instanceof PermissionCheckedCollection)
|
||||
@@ -126,37 +126,36 @@ public interface PermissionCheckedCollection<T>
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a {@link PermissionCheckedCollection} from an existing <code>Collection</code>
|
||||
*
|
||||
* @param <TT> the type of the <code>Collection</code>
|
||||
* @param collection the <code>Collection</code> to proxy
|
||||
* @param isCutOff <tt>true</tt> if permission checking was cut off before completion
|
||||
* @param sizeUnchecked number of entries from the original collection that were not checked
|
||||
* @param sizeOriginal number of entries in the original, pre-checked collection
|
||||
* @return a <code>Collection</code> of the same type but including the
|
||||
* {@link PermissionCheckedCollection} interface
|
||||
* @param <TT>
|
||||
* the type of the <code>Collection</code>
|
||||
* @param collection
|
||||
* the <code>Collection</code> to proxy
|
||||
* @param isCutOff
|
||||
* <tt>true</tt> if permission checking was cut off before completion
|
||||
* @param sizeUnchecked
|
||||
* number of entries from the original collection that were not checked
|
||||
* @param sizeOriginal
|
||||
* number of entries in the original, pre-checked collection
|
||||
* @return a <code>Collection</code> of the same type but including the {@link PermissionCheckedCollection} interface
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final <TT> Collection<TT> create(
|
||||
public static <TT> Collection<TT> create(
|
||||
Collection<TT> collection,
|
||||
boolean isCutOff, int sizeUnchecked, int sizeOriginal)
|
||||
{
|
||||
// Create the mixin
|
||||
DelegatingIntroductionInterceptor mixin = new PermissionCheckedCollectionMixin<Integer>(
|
||||
DelegatingIntroductionInterceptor mixin = new PermissionCheckedCollectionMixin<>(
|
||||
isCutOff,
|
||||
sizeUnchecked,
|
||||
sizeOriginal
|
||||
);
|
||||
sizeOriginal);
|
||||
// Create the advisor
|
||||
IntroductionAdvisor advisor = new DefaultIntroductionAdvisor(mixin, PermissionCheckedCollection.class);
|
||||
// Proxy
|
||||
ProxyFactory pf = new ProxyFactory(collection);
|
||||
pf.addAdvisor(advisor);
|
||||
Object proxiedObject = pf.getProxy();
|
||||
|
||||
// Done
|
||||
return (Collection<TT>) proxiedObject;
|
||||
// Create Proxy
|
||||
return (Collection<TT>) ProxyFactoryUtils.createProxy(collection, advisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
class ProxyFactoryUtils
|
||||
{
|
||||
private ProxyFactoryUtils()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Delegate creation of {@link ProxyFactory} and proxy to have control over it in one place.
|
||||
*
|
||||
* @param collection
|
||||
* given collection for ProxyFactory.
|
||||
* @param advisor
|
||||
* given advisor for ProxyFactory.
|
||||
* @return the proxy object.
|
||||
*/
|
||||
protected static Object createProxy(Collection<?> collection, IntroductionAdvisor advisor)
|
||||
{
|
||||
ProxyFactory pf = new ProxyFactory(collection);
|
||||
pf.addAdvisor(advisor);
|
||||
if (pf.isInterfaceProxied(List.class) && pf.isInterfaceProxied(Deque.class))
|
||||
{
|
||||
pf.removeInterface(Deque.class);
|
||||
}
|
||||
return pf.getProxy();
|
||||
}
|
||||
}
|
@@ -25,12 +25,17 @@
|
||||
*/
|
||||
package org.alfresco.repo.cache.lookup;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.sql.Savepoint;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
|
||||
import org.alfresco.repo.cache.MemoryCache;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
@@ -38,20 +43,16 @@ import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAO;
|
||||
import org.alfresco.repo.domain.control.ControlDAO;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
|
||||
/**
|
||||
* A cache for two-way lookups of database entities. These are characterized by having a unique
|
||||
* key (perhaps a database ID) and a separate unique key that identifies the object.
|
||||
* A cache for two-way lookups of database entities. These are characterized by having a unique key (perhaps a database ID) and a separate unique key that identifies the object.
|
||||
* <p>
|
||||
* The keys must have good <code>equals</code> and </code>hashCode</code> implementations and
|
||||
* must respect the case-sensitivity of the use-case.
|
||||
* The keys must have good <code>equals</code> and </code>hashCode</code> implementations and must respect the case-sensitivity of the use-case.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.2
|
||||
*/
|
||||
public class EntityLookupCacheTest extends TestCase implements EntityLookupCallbackDAO<Long, Object, String>
|
||||
public class EntityLookupCacheTest implements EntityLookupCallbackDAO<Long, Object, String>
|
||||
{
|
||||
SimpleCache<Long, Object> cache;
|
||||
private EntityLookupCache<Long, Object, String> entityLookupCacheA;
|
||||
@@ -59,7 +60,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
private TreeMap<Long, String> database;
|
||||
private ControlDAO controlDAO;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
cache = new MemoryCache<Long, Object>();
|
||||
@@ -71,6 +72,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
Mockito.when(controlDAO.createSavepoint(Mockito.anyString())).thenReturn(Mockito.mock(Savepoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupsUsingIncorrectValue() throws Exception
|
||||
{
|
||||
try
|
||||
@@ -84,6 +86,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupAgainstEmpty() throws Exception
|
||||
{
|
||||
TestValue value = new TestValue("AAA");
|
||||
@@ -114,6 +117,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals("Looked-up type value incorrect", value, entityPair.getSecond());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupAgainstExisting() throws Exception
|
||||
{
|
||||
// Put some values in the "database"
|
||||
@@ -136,6 +140,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals("ID is incorrect", Long.valueOf(3), entityPair.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegions() throws Exception
|
||||
{
|
||||
TestValue valueAAA = new TestValue("AAA");
|
||||
@@ -157,6 +162,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(8, cache.getKeys().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullLookups() throws Exception
|
||||
{
|
||||
TestValue valueNull = null;
|
||||
@@ -174,9 +180,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(entityPairNull, entityPairCheck);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrCreate() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
@@ -188,24 +195,27 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(id, entityPairOneCheck.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOrGet() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
assertEquals(valueOne.val, database.get(id));
|
||||
assertEquals(1, cache.getKeys().size());
|
||||
// We cache both by value and by key, so we should have 2 entries
|
||||
assertEquals(2, cache.getKeys().size());
|
||||
|
||||
Pair<Long, Object> entityPairOneCheck = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
||||
assertNotNull(entityPairOneCheck);
|
||||
assertEquals(id, entityPairOneCheck.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueTwo = new TestValue(getName() + "-TWO");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
TestValue valueTwo = new TestValue(getClass().getName() + "-TWO");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
@@ -219,9 +229,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(2, cache.getKeys().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteByKey() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
@@ -235,9 +246,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(0, cache.getKeys().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteByValue() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
@@ -251,9 +263,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(0, cache.getKeys().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() throws Exception
|
||||
{
|
||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
||||
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
@@ -266,16 +279,42 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
assertEquals(0, cache.getKeys().size()); // ... but cache must be empty
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCachedValue() throws Exception
|
||||
{
|
||||
// Create a new value
|
||||
TestValue valueCached = new TestValue(getClass().getName() + "-CACHED");
|
||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.createOrGetByValue(valueCached, controlDAO);
|
||||
assertNotNull(entityPairOne);
|
||||
Long id = entityPairOne.getFirst();
|
||||
// We cache both by value and by key, so we should have 2 entries
|
||||
assertEquals(2, cache.getKeys().size());
|
||||
|
||||
// Check the cache for the previously created value
|
||||
Pair<Long, Object> entityPairCacheCheck = entityLookupCacheA.getCachedEntityByValue(valueCached);
|
||||
assertNotNull(entityPairCacheCheck);
|
||||
assertEquals(id, entityPairCacheCheck.getFirst());
|
||||
|
||||
// Clear the cache and attempt to retrieve it again
|
||||
entityLookupCacheA.clear();
|
||||
entityPairCacheCheck = entityLookupCacheA.getCachedEntityByValue(valueCached);
|
||||
|
||||
// Since we are only retrieving from cache, the value should not be found
|
||||
assertNull(entityPairCacheCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to represent business object
|
||||
*/
|
||||
private static class TestValue
|
||||
{
|
||||
private final String val;
|
||||
|
||||
private TestValue(String val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
@@ -283,8 +322,9 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return val.equals( ((TestValue)obj).val );
|
||||
return val.equals(((TestValue) obj).val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
@@ -297,7 +337,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
{
|
||||
assertNotNull(value);
|
||||
assertTrue(value instanceof TestValue);
|
||||
String dbValue = ((TestValue)value).val;
|
||||
String dbValue = ((TestValue) value).val;
|
||||
return dbValue;
|
||||
}
|
||||
|
||||
@@ -318,7 +358,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
public Pair<Long, Object> findByValue(Object value)
|
||||
{
|
||||
assertTrue(value == null || value instanceof TestValue);
|
||||
String dbValue = (value == null) ? null : ((TestValue)value).val;
|
||||
String dbValue = (value == null) ? null : ((TestValue) value).val;
|
||||
|
||||
for (Map.Entry<Long, String> entry : database.entrySet())
|
||||
{
|
||||
@@ -336,7 +376,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
public Pair<Long, Object> createValue(Object value)
|
||||
{
|
||||
assertTrue(value == null || value instanceof TestValue);
|
||||
String dbValue = (value == null) ? null : ((TestValue)value).val;
|
||||
String dbValue = (value == null) ? null : ((TestValue) value).val;
|
||||
|
||||
// Kick out any duplicate values
|
||||
if (database.containsValue(dbValue))
|
||||
@@ -372,7 +412,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
||||
}
|
||||
else
|
||||
{
|
||||
database.put(key, ((TestValue)value).val);
|
||||
database.put(key, ((TestValue) value).val);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ services:
|
||||
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"
|
||||
keycloak:
|
||||
profiles: ["with-sso"]
|
||||
image: quay.io/keycloak/keycloak:24.0.3
|
||||
image: quay.io/keycloak/keycloak:25.0.6
|
||||
environment:
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=admin
|
||||
|
Reference in New Issue
Block a user