[MNT-24127] Added Endpoint To Calculate Folder Size (#2709)

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [MNT-24127] Added Endpoint to Calculate Size of the folder with Integration Test Cases [ags][tas]

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] EndpointToCalculateFolderSize

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* [feature/MNT-24127] Endpoint Added To Calculate Folder Size

* Some Optimization for NodeSize Calculation.

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added Endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoint to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding performance test case

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoints implementation to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoints implementation to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoints implementation to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Added endpoints implementation to calculate folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Adding endpoints to calculate and retrieve folder size

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* Changes as per the Relationship Api Framework implementation.

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments related to calculate and retrieve folder size details

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments and refactoring files

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments and refactoring files

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments and refactoring files

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments and refactoring files

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments regarding Integeration testcases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments regarding Integeration testcases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Addressing review comments

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Creating Integeration test cases

* [feature/MNT-24127-EndpointToCalculateFolderSize] Some Changes in NodeSizeDetailsTests

* [feature/MNT-24127-EndpointToCalculateFolderSize] Some Changes in NodeSizeDetailsTests

* [feature/MNT-24127-EndpointToCalculateFolderSize] Some Changes in NodeSizeDetailsTests

* [feature/MNT-24127-EndpointToCalculateFolderSize] Some Changes in NodeSizeDetailsTests

* [feature/MNT-24127-EndpointToCalculateFolderSize] Checking size-details feature for solr6 subsystem

* [feature/MNT-24127-EndpointToCalculateFolderSize] Checking size-details feature for solr6 subsystem

---------

Co-authored-by: kshah <kavit.shah@globallogic.com>
Co-authored-by: mohit-singh4 <mohit.singh@contractors.hyland.com>
Co-authored-by: kshah <kavit.shah@hyland.com>
This commit is contained in:
mohit-singh4
2024-11-08 15:37:27 +05:30
committed by GitHub
parent 25e9bdbdb6
commit a35673d44f
19 changed files with 2017 additions and 293 deletions

View File

@@ -731,7 +731,7 @@
"filename": "remote-api/src/test/java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java", "filename": "remote-api/src/test/java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java",
"hashed_secret": "d033e22ae348aeb5660fc2140aec35850c4da997", "hashed_secret": "d033e22ae348aeb5660fc2140aec35850c4da997",
"is_verified": false, "is_verified": false,
"line_number": 120, "line_number": 111,
"is_secret": false "is_secret": false
} }
], ],
@@ -1888,5 +1888,5 @@
} }
] ]
}, },
"generated_at": "2024-10-02T10:18:47Z" "generated_at": "2024-10-09T09:32:52Z"
} }

View File

@@ -0,0 +1,141 @@
/*-
* #%L
* alfresco-tas-restapi
* %%
* 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
* 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.model;
import java.util.Date;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.alfresco.rest.core.IRestModel;
import org.alfresco.utility.model.TestModel;
public class RestSizeDetailsModel extends TestModel implements IRestModel<RestSizeDetailsModel>
{
@JsonProperty(value = "entry")
RestSizeDetailsModel model;
private String id;
private Long sizeInBytes;
private Date calculatedAt;
private Integer numberOfFiles;
private String jobId;
private STATUS status;
public enum STATUS
{
NOT_INITIATED, PENDING, IN_PROGRESS, COMPLETED, FAILED
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public Long getSizeInBytes()
{
return sizeInBytes;
}
public void setSizeInBytes(Long sizeInBytes)
{
this.sizeInBytes = sizeInBytes;
}
public Date getCalculatedAt()
{
return calculatedAt;
}
public void setCalculatedAt(Date calculatedAt)
{
this.calculatedAt = calculatedAt;
}
public Integer getNumberOfFiles()
{
return numberOfFiles;
}
public void setNumberOfFiles(Integer numberOfFiles)
{
this.numberOfFiles = numberOfFiles;
}
public String getJobId()
{
return jobId;
}
public void setJobId(String jobId)
{
this.jobId = jobId;
}
public STATUS getStatus()
{
return status;
}
public void setStatus(STATUS status)
{
this.status = status;
}
@Override
public RestSizeDetailsModel onModel()
{
return model;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
RestSizeDetailsModel that = (RestSizeDetailsModel) o;
return Objects.equals(id, that.id) && Objects.equals(sizeInBytes, that.sizeInBytes) && Objects.equals(
calculatedAt, that.calculatedAt) && Objects.equals(numberOfFiles, that.numberOfFiles)
&& Objects.equals(jobId, that.jobId) && status == that.status;
}
@Override
public int hashCode()
{
return Objects.hash(id, sizeInBytes, calculatedAt, numberOfFiles, jobId, status);
}
}

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* alfresco-tas-restapi * alfresco-tas-restapi
* %% * %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -26,59 +26,34 @@
package org.alfresco.rest.requests; package org.alfresco.rest.requests;
import static org.alfresco.rest.core.JsonBodyGenerator.arrayToJson;
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
import static org.springframework.http.HttpMethod.PUT; import static org.springframework.http.HttpMethod.PUT;
import jakarta.json.JsonArrayBuilder; import static org.alfresco.rest.core.JsonBodyGenerator.arrayToJson;
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import jakarta.json.JsonArrayBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.testng.reporters.Files;
import org.alfresco.rest.core.JsonBodyGenerator; import org.alfresco.rest.core.JsonBodyGenerator;
import org.alfresco.rest.core.RestRequest; import org.alfresco.rest.core.RestRequest;
import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.core.RestResponse;
import org.alfresco.rest.core.RestWrapper; import org.alfresco.rest.core.RestWrapper;
import org.alfresco.rest.exception.JsonToModelConversionException; import org.alfresco.rest.exception.JsonToModelConversionException;
import org.alfresco.rest.model.RestActionDefinitionModelsCollection; import org.alfresco.rest.model.*;
import org.alfresco.rest.model.RestCategoryLinkBodyModel;
import org.alfresco.rest.model.RestCategoryModel;
import org.alfresco.rest.model.RestCategoryModelsCollection;
import org.alfresco.rest.model.RestCommentModel;
import org.alfresco.rest.model.RestCommentModelsCollection;
import org.alfresco.rest.model.RestNodeAssocTargetModel;
import org.alfresco.rest.model.RestNodeAssociationModel;
import org.alfresco.rest.model.RestNodeAssociationModelCollection;
import org.alfresco.rest.model.RestNodeAssociationTypeModel;
import org.alfresco.rest.model.RestNodeBodyModel;
import org.alfresco.rest.model.RestNodeBodyMoveCopyModel;
import org.alfresco.rest.model.RestNodeChildAssocModelCollection;
import org.alfresco.rest.model.RestNodeChildAssociationModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestNodeModelsCollection;
import org.alfresco.rest.model.RestRatingModel;
import org.alfresco.rest.model.RestRatingModelsCollection;
import org.alfresco.rest.model.RestRenditionInfoModel;
import org.alfresco.rest.model.RestRenditionInfoModelCollection;
import org.alfresco.rest.model.RestRuleExecutionModel;
import org.alfresco.rest.model.RestRuleSetLinkModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.rest.model.RestRuleSetModelsCollection;
import org.alfresco.rest.model.RestTagModel;
import org.alfresco.rest.model.RestTagModelsCollection;
import org.alfresco.rest.model.RestVersionModel;
import org.alfresco.rest.model.RestVersionModelsCollection;
import org.alfresco.rest.model.body.RestNodeLockBodyModel; import org.alfresco.rest.model.body.RestNodeLockBodyModel;
import org.alfresco.rest.model.builder.NodesBuilder; import org.alfresco.rest.model.builder.NodesBuilder;
import org.alfresco.utility.Utility; import org.alfresco.utility.Utility;
import org.alfresco.utility.model.RepoTestModel; import org.alfresco.utility.model.RepoTestModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.testng.reporters.Files;
/** /**
* Declares all Rest API under the /nodes path * Declares all Rest API under the /nodes path
@@ -294,6 +269,7 @@ public class Node extends ModelRequest<Node>
/** /**
* *
* Get fivestar rating of a document using GET call on "nodes/{nodeId}/ratings/{ratingId}" * Get fivestar rating of a document using GET call on "nodes/{nodeId}/ratings/{ratingId}"
*
* @return * @return
*/ */
public RestRatingModel getFiveStarRating() public RestRatingModel getFiveStarRating()
@@ -336,7 +312,6 @@ public class Node extends ModelRequest<Node>
return restWrapper.processModels(RestTagModelsCollection.class, request); return restWrapper.processModels(RestTagModelsCollection.class, request);
} }
/** /**
* Deletes a tag for a specific content node using DELETE call on nodes/{nodeId}/tags/{tagId} * Deletes a tag for a specific content node using DELETE call on nodes/{nodeId}/tags/{tagId}
* *
@@ -381,6 +356,7 @@ public class Node extends ModelRequest<Node>
* You need to specify first the multipart call {@link RestWrapper#usingMultipartFile(java.io.File)} * You need to specify first the multipart call {@link RestWrapper#usingMultipartFile(java.io.File)}
* *
* <code>usingMultipartFile(new File("your-local-file.txt")).withCoreAPI().usingNode(ContentModel.my()).createNode();</code> * <code>usingMultipartFile(new File("your-local-file.txt")).withCoreAPI().usingNode(ContentModel.my()).createNode();</code>
*
* @return * @return
*/ */
public RestNodeModel createNode() public RestNodeModel createNode()
@@ -415,7 +391,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Create node rendition using POST call on '/nodes/{nodeId}/renditions' * Create node rendition using POST call on '/nodes/{nodeId}/renditions'
* *
* @param renditionId id of rendition to be created * @param renditionId
* id of rendition to be created
* @return * @return
*/ */
public void createNodeRendition(String renditionId) public void createNodeRendition(String renditionId)
@@ -428,8 +405,10 @@ public class Node extends ModelRequest<Node>
/** /**
* Create node version rendition using POST call on '/nodes/{nodeId}/versions/{versionId}/renditions' * Create node version rendition using POST call on '/nodes/{nodeId}/versions/{versionId}/renditions'
* *
* @param renditionId id of rendition to be created * @param renditionId
* @param versionId version id of node * id of rendition to be created
* @param versionId
* version id of node
* @return * @return
*/ */
public void createNodeVersionRendition(String renditionId, String versionId) public void createNodeVersionRendition(String renditionId, String versionId)
@@ -442,10 +421,10 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Check if specified rendition exists and if not * Check if specified rendition exists and if not create node rendition using POST call on '/nodes/{nodeId}/renditions'
* create node rendition using POST call on '/nodes/{nodeId}/renditions'
* *
* @param renditionId id of rendition to be created * @param renditionId
* id of rendition to be created
* @return * @return
*/ */
public void createNodeRenditionIfNotExists(String renditionId) public void createNodeRenditionIfNotExists(String renditionId)
@@ -460,9 +439,10 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node rendition using GET call on '/nodes/{nodeId}/renditions/{renditionId} * Get node rendition using GET call on '/nodes/{nodeId}/renditions/{renditionId}
* *
* @param renditionId id of rendition to be retrieved * @param renditionId
* id of rendition to be retrieved
* @return * @return
*/ */
public RestRenditionInfoModel getNodeRendition(String renditionId) public RestRenditionInfoModel getNodeRendition(String renditionId)
@@ -474,8 +454,10 @@ public class Node extends ModelRequest<Node>
/** /**
* Get node version rendition using GET call on '/nodes/{nodeId}/versions/{versionId}renditions/{renditionId} * Get node version rendition using GET call on '/nodes/{nodeId}/versions/{versionId}renditions/{renditionId}
* *
* @param renditionId id of rendition to be retrieved * @param renditionId
* @param versionId versionId of the node * id of rendition to be retrieved
* @param versionId
* versionId of the node
* @return * @return
*/ */
public RestRenditionInfoModel getNodeVersionRendition(String renditionId, String versionId) public RestRenditionInfoModel getNodeVersionRendition(String renditionId, String versionId)
@@ -487,8 +469,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node rendition using GET call on 'nodes/{nodeId}/renditions/{renditionId} Please note that it retries to get * Get node rendition using GET call on 'nodes/{nodeId}/renditions/{renditionId} Please note that it retries to get the renditions response several times because on the alfresco server the rendition can take a while to be created.
* the renditions response several times because on the alfresco server the rendition can take a while to be created.
* *
* @return * @return
*/ */
@@ -510,8 +491,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node version rendition using GET call on 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId} Please note that it retries to get * Get node version rendition using GET call on 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId} Please note that it retries to get the renditions response several times because on the alfresco server the rendition can take a while to be created.
* the renditions response several times because on the alfresco server the rendition can take a while to be created.
* *
* @return * @return
*/ */
@@ -533,10 +513,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node rendition content using GET call on * Get node rendition content using GET call on 'nodes/{nodeId}/renditions/{renditionId}/content Please note that it retries to get the renditions response several times because on the alfresco server the rendition can take a while to be created.
* 'nodes/{nodeId}/renditions/{renditionId}/content Please note that it
* retries to get the renditions response several times because on the
* alfresco server the rendition can take a while to be created.
* *
* @return * @return
*/ */
@@ -546,7 +523,7 @@ public class Node extends ModelRequest<Node>
renditionId); renditionId);
RestResponse response = restWrapper.process(request); RestResponse response = restWrapper.process(request);
int retry = 0; int retry = 0;
//Multiplied by '8' because AI rendition test cases need more time (~30 seconds) - see ACS-2158 // Multiplied by '8' because AI rendition test cases need more time (~30 seconds) - see ACS-2158
while (!Integer.valueOf(response.getStatusCode()).equals(HttpStatus.OK.value()) && retry < (8 * Utility.retryCountSeconds)) while (!Integer.valueOf(response.getStatusCode()).equals(HttpStatus.OK.value()) && retry < (8 * Utility.retryCountSeconds))
{ {
Utility.waitToLoopTime(1); Utility.waitToLoopTime(1);
@@ -558,10 +535,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node version rendition content using GET call on * Get node version rendition content using GET call on 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId}/content Please note that it retries to get the renditions response several times because on the alfresco server the rendition can take a while to be created.
* 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId}/content Please note that it
* retries to get the renditions response several times because on the
* alfresco server the rendition can take a while to be created.
* *
* @return * @return
*/ */
@@ -582,8 +556,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node rendition content using GET call on * Get node rendition content using GET call on 'nodes/{nodeId}/renditions/{renditionId}/content
* 'nodes/{nodeId}/renditions/{renditionId}/content
* *
* @return * @return
*/ */
@@ -595,8 +568,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get node version rendition content using GET call on * Get node version rendition content using GET call on 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId}/content
* 'nodes/{nodeId}/versions/{versionId}/renditions/{renditionId}/content
* *
* @return * @return
*/ */
@@ -608,8 +580,8 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get rendition information for available renditions for the node using GET call on * Get rendition information for available renditions for the node using GET call on 'nodes/{nodeId}/renditions'
* 'nodes/{nodeId}/renditions' *
* @return * @return
*/ */
public RestRenditionInfoModelCollection getNodeRenditionsInfo() public RestRenditionInfoModelCollection getNodeRenditionsInfo()
@@ -620,8 +592,8 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Get rendition information for available renditions for the node version using GET call on * Get rendition information for available renditions for the node version using GET call on 'nodes/{nodeId}/versions/{versionId}/renditions'
* 'nodes/{nodeId}/versions/{versionId}/renditions' *
* @return * @return
*/ */
public RestRenditionInfoModelCollection getNodeVersionRenditionsInfo(String versionId) public RestRenditionInfoModelCollection getNodeVersionRenditionsInfo(String versionId)
@@ -631,11 +603,11 @@ public class Node extends ModelRequest<Node>
return restWrapper.processModels(RestRenditionInfoModelCollection.class, request); return restWrapper.processModels(RestRenditionInfoModelCollection.class, request);
} }
/** /**
* Delete the rendition identified by renditionId using DELETE call on "/nodes/{nodeId}/renditions/{renditionId}" * Delete the rendition identified by renditionId using DELETE call on "/nodes/{nodeId}/renditions/{renditionId}"
* *
* @param renditionId id of rendition to delete * @param renditionId
* id of rendition to delete
*/ */
public void deleteNodeRendition(String renditionId) public void deleteNodeRendition(String renditionId)
{ {
@@ -657,7 +629,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Move a node to a target folder * Move a node to a target folder
* *
* @param moveBody a {@link RestNodeBodyMoveCopyModel} containing at least the target parent id * @param moveBody
* a {@link RestNodeBodyMoveCopyModel} containing at least the target parent id
* @return the moved node's new information * @return the moved node's new information
*/ */
public RestNodeModel move(RestNodeBodyMoveCopyModel moveBody) public RestNodeModel move(RestNodeBodyMoveCopyModel moveBody)
@@ -669,7 +642,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Copy a node to a target folder * Copy a node to a target folder
* *
* @param copyBody a {@link RestNodeBodyMoveCopyModel} containing at least the target parent id * @param copyBody
* a {@link RestNodeBodyMoveCopyModel} containing at least the target parent id
* @return the moved node's new information * @return the moved node's new information
*/ */
public RestNodeModel copy(RestNodeBodyMoveCopyModel copyBody) public RestNodeModel copy(RestNodeBodyMoveCopyModel copyBody)
@@ -679,7 +653,6 @@ public class Node extends ModelRequest<Node>
return restWrapper.processModel(RestNodeModel.class, request); return restWrapper.processModel(RestNodeModel.class, request);
} }
/** /**
* Lock a specific node using POST call on "nodes/{nodeId}/lock" * Lock a specific node using POST call on "nodes/{nodeId}/lock"
* *
@@ -747,8 +720,7 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Delete a target for a specific node using DELETE call on * Delete a target for a specific node using DELETE call on nodes/{nodeId}/targets/{targetId}
* nodes/{nodeId}/targets/{targetId}
* *
* @param target * @param target
*/ */
@@ -830,7 +802,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param secondaryChild - node, which should become a secondary child * @param secondaryChild
* - node, which should become a secondary child
* @return a node's parent-child association * @return a node's parent-child association
*/ */
public RestNodeChildAssociationModel addSecondaryChild(RepoTestModel secondaryChild) public RestNodeChildAssociationModel addSecondaryChild(RepoTestModel secondaryChild)
@@ -841,8 +814,10 @@ public class Node extends ModelRequest<Node>
/** /**
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param associationType - type of secondary parent-child relationship association * @param associationType
* @param secondaryChild - node, which should become a secondary child * - type of secondary parent-child relationship association
* @param secondaryChild
* - node, which should become a secondary child
* @return a node's parent-child association * @return a node's parent-child association
*/ */
public RestNodeChildAssociationModel addSecondaryChild(String associationType, RepoTestModel secondaryChild) public RestNodeChildAssociationModel addSecondaryChild(String associationType, RepoTestModel secondaryChild)
@@ -853,7 +828,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param secondaryChildAssociation - node's secondary parent-child association model * @param secondaryChildAssociation
* - node's secondary parent-child association model
* @return a node's parent-child association * @return a node's parent-child association
*/ */
public RestNodeChildAssociationModel addSecondaryChild(RestNodeChildAssociationModel secondaryChildAssociation) public RestNodeChildAssociationModel addSecondaryChild(RestNodeChildAssociationModel secondaryChildAssociation)
@@ -865,7 +841,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param secondaryChildren - nodes, which should become secondary children * @param secondaryChildren
* - nodes, which should become secondary children
* @return a collection of node's parent-child associations * @return a collection of node's parent-child associations
*/ */
public RestNodeChildAssocModelCollection addSecondaryChildren(RepoTestModel... secondaryChildren) public RestNodeChildAssocModelCollection addSecondaryChildren(RepoTestModel... secondaryChildren)
@@ -876,21 +853,24 @@ public class Node extends ModelRequest<Node>
/** /**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param associationType - type of secondary parent-child relationship association * @param associationType
* @param secondaryChildren - nodes, which should become secondary children * - type of secondary parent-child relationship association
* @param secondaryChildren
* - nodes, which should become secondary children
* @return a collection of node's parent-child associations * @return a collection of node's parent-child associations
*/ */
public RestNodeChildAssocModelCollection addSecondaryChildren(String associationType, RepoTestModel... secondaryChildren) public RestNodeChildAssocModelCollection addSecondaryChildren(String associationType, RepoTestModel... secondaryChildren)
{ {
return addSecondaryChildren(Stream.of(secondaryChildren) return addSecondaryChildren(Stream.of(secondaryChildren)
.map(child -> new RestNodeChildAssociationModel(child.getNodeRef(), associationType)) .map(child -> new RestNodeChildAssociationModel(child.getNodeRef(), associationType))
.toArray(RestNodeChildAssociationModel[]::new)); .toArray(RestNodeChildAssociationModel[]::new));
} }
/** /**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'. * Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
* *
* @param secondaryChildrenAssociations - node's secondary parent-child association models * @param secondaryChildrenAssociations
* - node's secondary parent-child association models
* @return a collection of node's parent-child associations * @return a collection of node's parent-child associations
*/ */
public RestNodeChildAssocModelCollection addSecondaryChildren(RestNodeChildAssociationModel... secondaryChildrenAssociations) public RestNodeChildAssocModelCollection addSecondaryChildren(RestNodeChildAssociationModel... secondaryChildrenAssociations)
@@ -903,7 +883,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'. * Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
* *
* @param secondaryChild - node, which should NOT be a secondary child anymore * @param secondaryChild
* - node, which should NOT be a secondary child anymore
*/ */
public void removeSecondaryChild(RepoTestModel secondaryChild) public void removeSecondaryChild(RepoTestModel secondaryChild)
{ {
@@ -913,8 +894,10 @@ public class Node extends ModelRequest<Node>
/** /**
* Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'. * Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
* *
* @param associationType - type of secondary parent-child relationship association * @param associationType
* @param secondaryChild - node, which should NOT be a secondary child anymore * - type of secondary parent-child relationship association
* @param secondaryChild
* - node, which should NOT be a secondary child anymore
*/ */
public void removeSecondaryChild(String associationType, RepoTestModel secondaryChild) public void removeSecondaryChild(String associationType, RepoTestModel secondaryChild)
{ {
@@ -932,13 +915,12 @@ public class Node extends ModelRequest<Node>
/** /**
* Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'. * Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
* *
* @param secondaryChildAssociation - node's secondary parent-child association to remove * @param secondaryChildAssociation
* - node's secondary parent-child association to remove
*/ */
public void removeSecondaryChild(RestNodeAssociationModel secondaryChildAssociation) public void removeSecondaryChild(RestNodeAssociationModel secondaryChildAssociation)
{ {
String parameters = StringUtils.isNotEmpty(secondaryChildAssociation.getAssociation().getAssocType()) ? String parameters = StringUtils.isNotEmpty(secondaryChildAssociation.getAssociation().getAssocType()) ? "assocType=" + secondaryChildAssociation.getAssociation().getAssocType() + "&" + restWrapper.getParameters() : restWrapper.getParameters();
"assocType=" + secondaryChildAssociation.getAssociation().getAssocType() + "&" + restWrapper.getParameters() :
restWrapper.getParameters();
RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/secondary-children/{childId}?{parameters}", repoModel.getNodeRef(), secondaryChildAssociation.getId(), parameters); RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/secondary-children/{childId}?{parameters}", repoModel.getNodeRef(), secondaryChildAssociation.getId(), parameters);
restWrapper.processEmptyModel(request); restWrapper.processEmptyModel(request);
} }
@@ -1013,7 +995,6 @@ public class Node extends ModelRequest<Node>
deleteNode(nodeModel.getId()); deleteNode(nodeModel.getId());
} }
/** /**
* Delete a specific node using DELETE call on nodes/{nodeId} * Delete a specific node using DELETE call on nodes/{nodeId}
* *
@@ -1035,6 +1016,7 @@ public class Node extends ModelRequest<Node>
/** /**
* Get Direct Access URL for a node * Get Direct Access URL for a node
*
* @param postBody * @param postBody
* @return * @return
*/ */
@@ -1055,6 +1037,7 @@ public class Node extends ModelRequest<Node>
/** /**
* Get Direct Access URL for a specific node rendition E.g "pdf" * Get Direct Access URL for a specific node rendition E.g "pdf"
*
* @param renditionId * @param renditionId
* @return * @return
*/ */
@@ -1067,6 +1050,7 @@ public class Node extends ModelRequest<Node>
/** /**
* Get Direct Access URL for a specific node version. E.g "1.1" * Get Direct Access URL for a specific node version. E.g "1.1"
*
* @param versionId * @param versionId
* @return * @return
*/ */
@@ -1079,6 +1063,7 @@ public class Node extends ModelRequest<Node>
/** /**
* Get Direct Access URL for a specific node version rendition. E.g ("1.1", "pdf") * Get Direct Access URL for a specific node version rendition. E.g ("1.1", "pdf")
*
* @param versionId * @param versionId
* @param renditionId * @param renditionId
* @return * @return
@@ -1132,7 +1117,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Get the specified rule set from a folder. * Get the specified rule set from a folder.
* *
* @param ruleSetId The id of the rule set. * @param ruleSetId
* The id of the rule set.
* @return The specified rule set. * @return The specified rule set.
*/ */
public RestRuleSetModel getRuleSet(String ruleSetId) public RestRuleSetModel getRuleSet(String ruleSetId)
@@ -1145,7 +1131,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Update a rule set on this folder - for example to reorder the rules. * Update a rule set on this folder - for example to reorder the rules.
* *
* @param ruleSet The updated rule set. * @param ruleSet
* The updated rule set.
* @return The updated rule set returned by the server. * @return The updated rule set returned by the server.
*/ */
public RestRuleSetModel updateRuleSet(RestRuleSetModel ruleSet) public RestRuleSetModel updateRuleSet(RestRuleSetModel ruleSet)
@@ -1188,7 +1175,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Try to delete a ruleset link performing a DELETE call on "/nodes/{folderNodeId}/rule-set-links/{rulesetId}" * Try to delete a ruleset link performing a DELETE call on "/nodes/{folderNodeId}/rule-set-links/{rulesetId}"
* *
* @param ruleSetId the id of the ruleset to be unlinked from the folder * @param ruleSetId
* the id of the ruleset to be unlinked from the folder
* @return * @return
*/ */
public void unlinkRuleSet(String ruleSetId) public void unlinkRuleSet(String ruleSetId)
@@ -1200,7 +1188,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Trigger rules on a folder performing POST call on "/nodes/{folderNodeId}/rule-executions" * Trigger rules on a folder performing POST call on "/nodes/{folderNodeId}/rule-executions"
* *
* @param body - rules execution request * @param body
* - rules execution request
* @return execution result * @return execution result
*/ */
public RestRuleExecutionModel executeRules(RestRuleExecutionModel body) public RestRuleExecutionModel executeRules(RestRuleExecutionModel body)
@@ -1223,7 +1212,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Link content to category performing POST call on "/nodes/{nodeId}/category-links" * Link content to category performing POST call on "/nodes/{nodeId}/category-links"
* *
* @param categoryLink - contains category ID * @param categoryLink
* - contains category ID
* @return linked to category * @return linked to category
*/ */
public RestCategoryModel linkToCategory(RestCategoryLinkBodyModel categoryLink) public RestCategoryModel linkToCategory(RestCategoryLinkBodyModel categoryLink)
@@ -1235,7 +1225,8 @@ public class Node extends ModelRequest<Node>
/** /**
* Link content to many categories performing POST call on "/nodes/{nodeId}/category-links" * Link content to many categories performing POST call on "/nodes/{nodeId}/category-links"
* *
* @param categoryLinks - contains categories IDs * @param categoryLinks
* - contains categories IDs
* @return linked to categories * @return linked to categories
*/ */
public RestCategoryModelsCollection linkToCategories(List<RestCategoryLinkBodyModel> categoryLinks) public RestCategoryModelsCollection linkToCategories(List<RestCategoryLinkBodyModel> categoryLinks)
@@ -1247,11 +1238,34 @@ public class Node extends ModelRequest<Node>
/** /**
* Unlink content from a category performing a DELETE call on "nodes/{nodeId}/category-links/{categoryId}" * Unlink content from a category performing a DELETE call on "nodes/{nodeId}/category-links/{categoryId}"
* *
* @param categoryId the id of the category to be unlinked from content * @param categoryId
* the id of the category to be unlinked from content
*/ */
public void unlinkFromCategory(String categoryId) public void unlinkFromCategory(String categoryId)
{ {
RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/category-links/{categoryId}", repoModel.getNodeRef(), categoryId); RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/category-links/{categoryId}", repoModel.getNodeRef(), categoryId);
restWrapper.processEmptyModel(request); restWrapper.processEmptyModel(request);
} }
/**
* In order to retrieve folder size details using POST call on "nodes/{nodeId}/size-details"
*
* @return
*/
public RestSizeDetailsModel executeSizeDetails()
{
RestRequest request = RestRequest.simpleRequest(HttpMethod.POST, "nodes/{nodeId}/size-details", repoModel.getNodeRef());
return restWrapper.processModel(RestSizeDetailsModel.class, request);
}
/**
* Getting Folder size details using GET call on "nodes/{nodeId}/size-details/{jobId}"
*
* @return
*/
public RestSizeDetailsModel getSizeDetails(String jobId)
{
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, "nodes/{nodeId}/size-details/{jobId}", repoModel.getNodeRef(), jobId);
return restWrapper.processModel(RestSizeDetailsModel.class, request);
}
} }

View File

@@ -0,0 +1,72 @@
package org.alfresco.rest.nodes;
import org.apache.commons.lang3.RandomStringUtils;
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.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
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;
public class NodeSizeDetailsTests extends RestTest
{
private UserModel user1;
private SiteModel siteModel;
private FolderModel folder;
@BeforeClass(alwaysRun = true)
public void dataPreparation()
{
user1 = dataUser.createRandomTestUser("User-1");
siteModel = dataSite.usingUser(user1).createPublicRandomSite();
folder = dataContent.usingUser(user1).usingSite(siteModel).createFolder(FolderModel.getRandomFolderModel());
}
/**
*
* Unauthenticated user not able to execute POST /nodes/{nodeId}/size-details: 401 STATUS CODE
*/
@TestRail(section = {TestGroup.REST_API, TestGroup.NODES}, executionType = ExecutionType.SANITY)
@Test(groups = {TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY})
public void unauthenticatedUserIsNotAbleGetSizeDetails()
{
restClient.authenticateUser(new UserModel("random user", "random password"));
restClient.withCoreAPI().usingNode(folder).executeSizeDetails();
restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED);
}
/**
* Node Id Not Exist: 404 STATUS CODE
*/
@TestRail(section = {TestGroup.REST_API, TestGroup.NODES}, executionType = ExecutionType.SANITY)
@Test(groups = {TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY})
public void nodeIdNotExist()
{
folder.setNodeRef(RandomStringUtils.randomAlphanumeric(20));
restClient.authenticateUser(user1).withCoreAPI().usingNode(folder).executeSizeDetails();
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND);
}
/**
*
* Value of nodeId is invalid: 422 STATUS CODE
*/
@TestRail(section = {TestGroup.REST_API, TestGroup.NODES}, executionType = ExecutionType.SANITY)
@Test(groups = {TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY})
public void nodeIdNotValid()
{
FileModel document = dataContent.usingSite(siteModel).usingUser(user1).createContent(DocumentType.TEXT_PLAIN);
restClient.authenticateUser(user1).withCoreAPI().usingNode(document).executeSizeDetails();
restClient.assertStatusCodeIs(HttpStatus.UNPROCESSABLE_ENTITY);
}
}

View File

@@ -0,0 +1,600 @@
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.
Sample text.

View File

@@ -0,0 +1,36 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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
* 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;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails;
public interface SizeDetails
{
NodeSizeDetails generateNodeSizeDetailsRequest(String nodeId);
NodeSizeDetails getNodeSizeDetails(String nodeId, String jobId);
}

View File

@@ -0,0 +1,119 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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
* 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 java.util.Optional;
import org.springframework.beans.factory.InitializingBean;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsService;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails.STATUS;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.SizeDetails;
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck;
public class SizeDetailsImpl implements SizeDetails, InitializingBean
{
private final Nodes nodes;
private final NodeSizeDetailsService nodeSizeDetailsService;
public SizeDetailsImpl(Nodes nodes, NodeSizeDetailsService nodeSizeDetailsService)
{
this.nodes = nodes;
this.nodeSizeDetailsService = nodeSizeDetailsService;
}
/**
* generateNodeSizeDetailsRequest : providing HTTP STATUS 202 with jobId.
*/
@Override
public NodeSizeDetails generateNodeSizeDetailsRequest(String nodeId)
{
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
validateType(nodeRef);
Optional<NodeSizeDetails> nodeSizeDetails = nodeSizeDetailsService.getSizeDetails(nodeId);
String actionId = nodeSizeDetails.map(NodeSizeDetails::getJobId)
.orElseGet(() -> executeSizeDetails(nodeRef));
return new NodeSizeDetails(actionId);
}
/**
* getNodeSizeDetails : providing HTTP STATUS 200 with NodeSizeDetails data from cache.
*/
@Override
public NodeSizeDetails getNodeSizeDetails(final String nodeId, final String jobId)
{
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
validateType(nodeRef);
Optional<NodeSizeDetails> optionalDetails = nodeSizeDetailsService.getSizeDetails(nodeId);
return optionalDetails.map(details -> {
String cachedJobId = details.getJobId();
if (cachedJobId != null && !jobId.equalsIgnoreCase(cachedJobId))
{
throw new NotFoundException("jobId does not exist");
}
return details;
})
.orElseGet(() -> new NodeSizeDetails(nodeId, STATUS.NOT_INITIATED));
}
/**
* Executing Asynchronously.
*/
private String executeSizeDetails(NodeRef nodeRef)
{
String jobId = GUID.generate();
NodeSizeDetails nodeSizeDetails = new NodeSizeDetails(nodeRef.getId(), jobId, STATUS.PENDING);
nodeSizeDetailsService.putSizeDetails(nodeRef.getId(), nodeSizeDetails);
nodeSizeDetailsService.invokeSizeDetailsExecutor(nodeRef, jobId);
return jobId;
}
private void validateType(NodeRef nodeRef) throws InvalidNodeTypeException
{
if (!nodes.isSubClass(nodeRef, ContentModel.TYPE_FOLDER, false))
{
throw new InvalidNodeTypeException("Node id " + nodeRef.getId() + " does not represent a folder.");
}
}
@Override
public void afterPropertiesSet() throws Exception
{
ParameterCheck.mandatory("nodes", this.nodes);
ParameterCheck.mandatory("nodeSizeDetailsServiceImpl", this.nodeSizeDetailsService);
}
}

View File

@@ -0,0 +1,84 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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
* 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.nodes;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.extensions.webscripts.Status;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails;
import org.alfresco.rest.api.SizeDetails;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.WebApiParameters;
import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.ParameterCheck;
@RelationshipResource(name = "size-details", entityResource = NodesEntityResource.class, title = "Node Size Details")
public class NodeSizeDetailsRelation implements RelationshipResourceAction.ReadById<NodeSizeDetails>,
RelationshipResourceAction.Create<NodeSizeDetails>, InitializingBean
{
private SizeDetails sizeDetails;
public void setSizeDetails(SizeDetails sizeDetails)
{
this.sizeDetails = sizeDetails;
}
@Override
public void afterPropertiesSet()
{
ParameterCheck.mandatory("sizeDetails", this.sizeDetails);
}
@WebApiDescription(title = "Create node-size details request", successStatus = Status.STATUS_ACCEPTED)
@WebApiParam(name = "nodeSizeEntity", title = "Node Size Details Request",
description = "Request for processing Node Size.", kind = ResourceParameter.KIND.HTTP_BODY_OBJECT,
allowMultiple = false)
@Override
public List<NodeSizeDetails> create(String nodeId, List<NodeSizeDetails> nodeSizeEntity, Parameters parameters)
{
return List.of(sizeDetails.generateNodeSizeDetailsRequest(nodeId));
}
@WebApiDescription(title = "Get Node Size Details", description = "Get the Node Size Details")
@WebApiParameters({@WebApiParam(name = "nodeId", title = "The unique id of the Node being addressed",
description = "A single Node id"),
@WebApiParam(name = "jobId", title = "Job Id to get the NodeSizeDetails", description = "JobId")})
@Override
public NodeSizeDetails readById(String nodeId, String jobId, Parameters parameters)
throws RelationshipResourceNotFoundException
{
return sizeDetails.getNodeSizeDetails(nodeId, jobId);
}
}

View File

@@ -996,6 +996,25 @@
</property> </property>
</bean> </bean>
<bean id="sizeDetailsImpl" class="org.alfresco.rest.api.impl.SizeDetailsImpl">
<constructor-arg name="nodes" ref="nodes" />
<constructor-arg name="nodeSizeDetailsService" ref="NodeSizeDetailsService" />
</bean>
<bean id="sizeDetails" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.SizeDetails</value>
</property>
<property name="target">
<ref bean="sizeDetailsImpl" />
</property>
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean class="org.alfresco.rest.api.rules.NodeRuleSettingsRelation"> <bean class="org.alfresco.rest.api.rules.NodeRuleSettingsRelation">
<property name="ruleSettings" ref="RuleSettings" /> <property name="ruleSettings" ref="RuleSettings" />
</bean> </bean>
@@ -1770,4 +1789,8 @@
</list> </list>
</property> </property>
</bean> </bean>
<bean class="org.alfresco.rest.api.nodes.NodeSizeDetailsRelation">
<property name="sizeDetails" ref="sizeDetails" />
</bean>
</beans> </beans>

View File

@@ -4,21 +4,21 @@
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
@@ -71,7 +71,7 @@ import org.junit.runners.Suite;
org.alfresco.rest.api.tests.TestPublicApiCaching.class, org.alfresco.rest.api.tests.TestPublicApiCaching.class,
org.alfresco.rest.api.tests.TestUserPreferences.class, org.alfresco.rest.api.tests.TestUserPreferences.class,
org.alfresco.rest.api.tests.WherePredicateApiTest.class, org.alfresco.rest.api.tests.WherePredicateApiTest.class,
org.alfresco.rest.api.tests.TestRemovePermissions.class, org.alfresco.rest.api.tests.TestRemovePermissions.class,
org.alfresco.rest.api.tests.TempOutputStreamTest.class, org.alfresco.rest.api.tests.TempOutputStreamTest.class,
org.alfresco.rest.api.tests.BufferedResponseTest.class, org.alfresco.rest.api.tests.BufferedResponseTest.class,
org.alfresco.rest.workflow.api.tests.DeploymentWorkflowApiTest.class, org.alfresco.rest.workflow.api.tests.DeploymentWorkflowApiTest.class,

View File

@@ -2,23 +2,23 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
@@ -36,6 +36,8 @@ import org.alfresco.util.testing.category.NonBuildTests;
@RunWith(Categories.class) @RunWith(Categories.class)
@Categories.ExcludeCategory({DBTests.class, NonBuildTests.class}) @Categories.ExcludeCategory({DBTests.class, NonBuildTests.class})
@Suite.SuiteClasses({ @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.quickshare.QuickShareRestApiTest.class,
org.alfresco.repo.web.scripts.admin.AdminWebScriptTest.class, org.alfresco.repo.web.scripts.admin.AdminWebScriptTest.class,
org.alfresco.repo.web.scripts.audit.AuditWebScriptTest.class, org.alfresco.repo.web.scripts.audit.AuditWebScriptTest.class,
@@ -47,8 +49,7 @@ import org.alfresco.util.testing.category.NonBuildTests;
org.alfresco.repo.web.scripts.forms.FormRestApiJsonPost_Test.class, org.alfresco.repo.web.scripts.forms.FormRestApiJsonPost_Test.class,
org.alfresco.repo.web.scripts.groups.GroupsTest.class, org.alfresco.repo.web.scripts.groups.GroupsTest.class,
org.alfresco.repo.web.scripts.invitation.InvitationWebScriptTest.class, org.alfresco.repo.web.scripts.invitation.InvitationWebScriptTest.class,
org.alfresco.repo.web.scripts.invite.InviteServiceTest.class, org.alfresco.repo.web.scripts.invite.InviteServiceTest.class, org.alfresco.repo.web.scripts.LoginTest.class,
org.alfresco.repo.web.scripts.LoginTest.class,
org.alfresco.repo.web.scripts.search.PersonSearchTest.class, org.alfresco.repo.web.scripts.search.PersonSearchTest.class,
org.alfresco.repo.web.scripts.person.PersonServiceTest.class, org.alfresco.repo.web.scripts.person.PersonServiceTest.class,
org.alfresco.repo.web.scripts.preference.PreferenceServiceTest.class, org.alfresco.repo.web.scripts.preference.PreferenceServiceTest.class,
@@ -76,9 +77,8 @@ import org.alfresco.util.testing.category.NonBuildTests;
org.alfresco.repo.web.scripts.node.NodeWebScripTest.class, org.alfresco.repo.web.scripts.node.NodeWebScripTest.class,
org.alfresco.rest.api.impl.CommentsImplUnitTest.class, org.alfresco.rest.api.impl.CommentsImplUnitTest.class,
org.alfresco.rest.api.impl.DownloadsImplCheckArchiveStatusUnitTest.class, org.alfresco.rest.api.impl.DownloadsImplCheckArchiveStatusUnitTest.class,
org.alfresco.rest.api.impl.FavouritesImplUnitTest.class, org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class,
org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class org.alfresco.rest.api.impl.SizeDetailsImplTest.class})
})
public class AppContext04TestSuite public class AppContext04TestSuite
{ {
public AppContext04TestSuite() public AppContext04TestSuite()

View File

@@ -0,0 +1,107 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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
* 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 org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.Optional;
import java.util.concurrent.ThreadPoolExecutor;
import org.junit.Before;
import org.junit.Test;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.QName;
/**
* Unit tests for {@link SizeDetailsImpl} class.
*/
public class SizeDetailsImplTest
{
private static final String NAMESPACE = "http://www.alfresco.org/test/NodeSizeDetailsTest";
private static final QName TYPE_FOLDER = QName.createQName(NAMESPACE, "folder");
private SizeDetailsImpl sizeDetailsImpl;
private Nodes nodes;
private NodeSizeDetailsServiceImpl nodeSizeDetailsServiceImpl;
private NodeSizeDetails nodeSizeDetails;
@Before
public void setUp() throws Exception
{
nodes = mock(Nodes.class);
SearchService searchService = mock(SearchService.class);
nodeSizeDetailsServiceImpl = mock(NodeSizeDetailsServiceImpl.class);
ThreadPoolExecutor threadPoolExecutor = mock(ThreadPoolExecutor.class);
SimpleCache<Serializable, NodeSizeDetails> simpleCache = mock(SimpleCache.class);
nodeSizeDetails = mock(NodeSizeDetails.class);
nodeSizeDetailsServiceImpl.setSearchService(searchService);
nodeSizeDetailsServiceImpl.setDefaultItems(1000);
nodeSizeDetailsServiceImpl.setSimpleCache(simpleCache);
verify(nodeSizeDetailsServiceImpl).setSimpleCache(simpleCache);
nodeSizeDetailsServiceImpl.setThreadPoolExecutor(threadPoolExecutor);
sizeDetailsImpl = new SizeDetailsImpl(nodes, nodeSizeDetailsServiceImpl);
}
@Test
public void calculateNodeSizeDetails()
{
String nodeName = "folderNode";
String nodeId = "node-id";
String jobId = "job-id";
NodeRef nodeRef = new NodeRef("protocol", "identifier", nodeId);
Node node = new Node();
node.setIsFolder(true);
node.setNodeRef(nodeRef);
node.setName(nodeName);
node.setNodeType(TYPE_FOLDER.getLocalName());
node.setNodeId(nodeRef.getId());
when(nodes.validateOrLookupNode(nodeId)).thenReturn(nodeRef);
when(nodes.isSubClass(nodeRef, ContentModel.TYPE_FOLDER, false)).thenReturn(true);
when(nodeSizeDetailsServiceImpl.getSizeDetails(nodeId)).thenReturn(Optional.ofNullable(nodeSizeDetails));
NodeSizeDetails requestSizeDetails = sizeDetailsImpl.generateNodeSizeDetailsRequest(nodeId);
assertNotNull("After executing POST/size-details, it will provide with 202 status code", requestSizeDetails);
NodeSizeDetails nodeSizeDetails = sizeDetailsImpl.getNodeSizeDetails(nodeId, jobId);
assertNotNull("After executing GET/size-details, it will provide with 200 status code", nodeSizeDetails);
}
}

View File

@@ -2,50 +2,68 @@
* #%L * #%L
* Alfresco Remote API * Alfresco Remote API
* %% * %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.rest.api.tests; package org.alfresco.rest.api.tests;
import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.rest.api.impl.directurl.RestApiDirectUrlConfig;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient;
import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsString;
import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsStringNonNull;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsString;
import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsStringNonNull;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.experimental.categories.Category;
import org.springframework.util.ResourceUtils;
import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.tenant.TenantUtil; import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.impl.directurl.RestApiDirectUrlConfig;
import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.model.Site;
import org.alfresco.rest.api.nodes.NodesEntityResource; import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.api.tests.RepoService.TestNetwork; import org.alfresco.rest.api.tests.RepoService.TestNetwork;
import org.alfresco.rest.api.tests.client.HttpResponse; import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient; import org.alfresco.rest.api.tests.client.PublicApiClient;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder; import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder;
import org.alfresco.rest.api.tests.client.RequestContext; import org.alfresco.rest.api.tests.client.RequestContext;
@@ -65,26 +83,10 @@ import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.alfresco.util.testing.category.LuceneTests; import org.alfresco.util.testing.category.LuceneTests;
import org.json.simple.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.experimental.categories.Category;
import org.springframework.util.ResourceUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
/** /**
* Generic methods for calling the Api (originally taken and adapted from BaseCustomModelApiTest) * Generic methods for calling the Api (originally taken and adapted from BaseCustomModelApiTest)
* *
* @author Jamal Kaabi-Mofrad * @author Jamal Kaabi-Mofrad
* @author janv * @author janv
* @author gethin * @author gethin
@@ -94,54 +96,40 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{ {
public static final String LAST_MODIFIED_HEADER = "Last-Modified"; public static final String LAST_MODIFIED_HEADER = "Last-Modified";
public static final String IF_MODIFIED_SINCE_HEADER = "If-Modified-Since"; public static final String IF_MODIFIED_SINCE_HEADER = "If-Modified-Since";
private static final String RESOURCE_PREFIX = "publicapi/upload/";
protected static final String URL_NODES = "nodes"; protected static final String URL_NODES = "nodes";
protected static final String URL_DELETED_NODES = "deleted-nodes"; protected static final String URL_DELETED_NODES = "deleted-nodes";
protected static final String URL_RENDITIONS = "renditions"; protected static final String URL_RENDITIONS = "renditions";
protected static final String URL_VERSIONS = "versions"; protected static final String URL_VERSIONS = "versions";
private static final String URL_CHILDREN = "children";
private static final String URL_CONTENT = "content";
protected static final String TYPE_CM_FOLDER = "cm:folder"; protected static final String TYPE_CM_FOLDER = "cm:folder";
protected static final String TYPE_CM_CONTENT = "cm:content"; protected static final String TYPE_CM_CONTENT = "cm:content";
protected static final String TYPE_CM_OBJECT = "cm:cmobject"; protected static final String TYPE_CM_OBJECT = "cm:cmobject";
protected static final String ASPECT_CM_PREFERENCES = "cm:preferences"; protected static final String ASPECT_CM_PREFERENCES = "cm:preferences";
protected static final String ASSOC_TYPE_CM_PREFERENCE_IMAGE = "cm:preferenceImage"; protected static final String ASSOC_TYPE_CM_PREFERENCE_IMAGE = "cm:preferenceImage";
protected static final String ASSOC_TYPE_CM_CONTAINS = "cm:contains"; protected static final String ASSOC_TYPE_CM_CONTAINS = "cm:contains";
// TODO improve admin-related tests, including ability to override default admin un/pw // TODO improve admin-related tests, including ability to override default admin un/pw
protected static final String DEFAULT_ADMIN = "admin"; protected static final String DEFAULT_ADMIN = "admin";
protected static final String DEFAULT_ADMIN_PWD = "admin"; protected static final String DEFAULT_ADMIN_PWD = "admin";
protected static final long PAUSE_TIME = 5000; // millisecond
protected static final int MAX_RETRY = 20;
private static final String RESOURCE_PREFIX = "publicapi/upload/";
private static final String URL_CHILDREN = "children";
private static final String URL_CONTENT = "content";
private static final String URL_CALCULATEFOLDERSIZE = "size-details";
private static final String REQUEST_DIRECT_ACCESS_URL = "request-direct-access-url";
// network1 with user1, user2 and a testsite1 // network1 with user1, user2 and a testsite1
protected static TestNetwork networkOne; protected static TestNetwork networkOne;
protected static String user1; // user1 from network1 protected static String user1; // user1 from network1
protected static String user2; // user2 from network1 protected static String user2; // user2 from network1
// network admin (or default super admin, if not running within a tenant/network) // network admin (or default super admin, if not running within a tenant/network)
protected static String networkAdmin = DEFAULT_ADMIN; protected static String networkAdmin = DEFAULT_ADMIN;
protected static String tSiteId; protected static String tSiteId;
protected static String tDocLibNodeId; protected static String tDocLibNodeId;
protected static List<String> users = new ArrayList<>(); protected static List<String> users = new ArrayList<>();
protected static JacksonUtil jacksonUtil; protected static JacksonUtil jacksonUtil;
protected static MutableAuthenticationService authenticationService; protected static MutableAuthenticationService authenticationService;
protected static PersonService personService; protected static PersonService personService;
protected final String RUNID = System.currentTimeMillis() + "";
protected final String RUNID = System.currentTimeMillis()+"";
private static final String REQUEST_DIRECT_ACCESS_URL = "request-direct-access-url";
@Override @Override
@Before @Before
public void setup() throws Exception public void setup() throws Exception
@@ -153,22 +141,22 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
// note: populateTestData/createTestData will be called (which currently creates 2 tenants, 9 users per tenant, 10 sites per tenant, ...) // note: populateTestData/createTestData will be called (which currently creates 2 tenants, 9 users per tenant, 10 sites per tenant, ...)
networkOne = getTestFixture().getRandomNetwork(); networkOne = getTestFixture().getRandomNetwork();
} }
//userOneN1 = networkN1.createUser(); // userOneN1 = networkN1.createUser();
//userTwoN1 = networkN1.createUser(); // userTwoN1 = networkN1.createUser();
String tenantDomain = networkOne.getId(); String tenantDomain = networkOne.getId();
if (! TenantService.DEFAULT_DOMAIN.equals(tenantDomain)) if (!TenantService.DEFAULT_DOMAIN.equals(tenantDomain))
{ {
networkAdmin = DEFAULT_ADMIN+"@"+tenantDomain; networkAdmin = DEFAULT_ADMIN + "@" + tenantDomain;
} }
// to enable admin access via test calls - eg. via PublicApiClient -> AbstractTestApi -> findUserByUserName // to enable admin access via test calls - eg. via PublicApiClient -> AbstractTestApi -> findUserByUserName
getOrCreateUser(networkAdmin, "admin", networkOne); getOrCreateUser(networkAdmin, "admin", networkOne);
setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD);
// note: createUser currently relies on repoService // note: createUser currently relies on repoService
user1 = createUser("user1-" + RUNID, "user1Password", networkOne); user1 = createUser("user1-" + RUNID, "user1Password", networkOne);
user2 = createUser("user2-" + RUNID, "user2Password", networkOne); user2 = createUser("user2-" + RUNID, "user2Password", networkOne);
@@ -180,7 +168,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
users.add(user2); users.add(user2);
setRequestContext(networkOne.getId(), user1, null); setRequestContext(networkOne.getId(), user1, null);
tSiteId = createSite("TestSite A - " + RUNID, SiteVisibility.PRIVATE).getId(); tSiteId = createSite("TestSite A - " + RUNID, SiteVisibility.PRIVATE).getId();
tDocLibNodeId = getSiteContainerNodeId(tSiteId, "documentLibrary"); tDocLibNodeId = getSiteContainerNodeId(tSiteId, "documentLibrary");
@@ -197,11 +185,10 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
setRequestContext(networkAdmin); setRequestContext(networkAdmin);
for (final String username : users) for (final String username : users)
{ {
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
{
@Override @Override
public Void execute() throws Throwable public Void execute() throws Throwable
{ {
@@ -210,7 +197,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
}); });
} }
users.clear(); users.clear();
AuthenticationUtil.clearCurrentSecurityContext(); AuthenticationUtil.clearCurrentSecurityContext();
setRequestContext(null); setRequestContext(null);
@@ -233,7 +220,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String getRequestArchivedRenditonContentDirectUrl(String nodeId, String renditionID) protected String getRequestArchivedRenditonContentDirectUrl(String nodeId, String renditionID)
{ {
return URL_DELETED_NODES + "/" + nodeId + "/" + URL_RENDITIONS + "/" + renditionID + "/" + REQUEST_DIRECT_ACCESS_URL; return URL_DELETED_NODES + "/" + nodeId + "/" + URL_RENDITIONS + "/" + renditionID + "/"
+ REQUEST_DIRECT_ACCESS_URL;
} }
protected String getRequestRenditionDirectAccessUrl(String nodeId, String renditionID) protected String getRequestRenditionDirectAccessUrl(String nodeId, String renditionID)
@@ -246,7 +234,6 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return URL_NODES + "/" + nodeId + "/" + URL_VERSIONS + "/" + versionId + "/" + REQUEST_DIRECT_ACCESS_URL; return URL_NODES + "/" + nodeId + "/" + URL_VERSIONS + "/" + versionId + "/" + REQUEST_DIRECT_ACCESS_URL;
} }
/** /**
* The api scope. either public or private * The api scope. either public or private
* *
@@ -262,10 +249,10 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse post(String url, byte[] body, Map<String, String> params, Map<String, String> headers, String apiName, String contentType, int expectedStatus) throws Exception protected HttpResponse post(String url, byte[] body, Map<String, String> params, Map<String, String> headers,
String apiName, String contentType, int expectedStatus) throws Exception
{ {
RequestBuilder requestBuilder = httpClient.new PostRequestBuilder() RequestBuilder requestBuilder = httpClient.new PostRequestBuilder().setBodyAsByteArray(body)
.setBodyAsByteArray(body)
.setContentType(contentType) .setContentType(contentType)
.setRequestContext(publicApiClient.getRequestContext()) .setRequestContext(publicApiClient.getRequestContext())
.setScope(getScope()) .setScope(getScope())
@@ -279,10 +266,10 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse post(String url, String body, Map<String, String> params, Map<String, String> headers, String apiName, int expectedStatus) throws Exception protected HttpResponse post(String url, String body, Map<String, String> params, Map<String, String> headers,
String apiName, int expectedStatus) throws Exception
{ {
RequestBuilder requestBuilder = httpClient.new PostRequestBuilder() RequestBuilder requestBuilder = httpClient.new PostRequestBuilder().setBodyAsString(body)
.setBodyAsString(body)
.setRequestContext(publicApiClient.getRequestContext()) .setRequestContext(publicApiClient.getRequestContext())
.setScope(getScope()) .setScope(getScope())
.setApiName(apiName) .setApiName(apiName)
@@ -307,7 +294,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse post(String url, String body, String queryString, String contentType, int expectedStatus) throws Exception protected HttpResponse post(String url, String body, String queryString, String contentType, int expectedStatus)
throws Exception
{ {
if (queryString != null) if (queryString != null)
{ {
@@ -319,7 +307,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse post(String url, byte[] body, String queryString, String contentType, int expectedStatus) throws Exception protected HttpResponse post(String url, byte[] body, String queryString, String contentType, int expectedStatus)
throws Exception
{ {
if (queryString != null) if (queryString != null)
{ {
@@ -332,9 +321,12 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
// TODO unused queryString - fix-up usages and then remove // TODO unused queryString - fix-up usages and then remove
protected HttpResponse post(String entityCollectionName, String entityId, String relationCollectionName, byte[] body, String queryString, String contentType, int expectedStatus) throws Exception protected HttpResponse post(String entityCollectionName, String entityId, String relationCollectionName,
byte[] body, String queryString, String contentType, int expectedStatus)
throws Exception
{ {
HttpResponse response = publicApiClient.post(getScope(), entityCollectionName, entityId, relationCollectionName, null, body, contentType); HttpResponse response = publicApiClient.post(getScope(), entityCollectionName, entityId, relationCollectionName, null, body,
contentType);
checkStatus(expectedStatus, response.getStatusCode()); checkStatus(expectedStatus, response.getStatusCode());
return response; return response;
@@ -345,7 +337,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return getAll(url, paging, null, expectedStatus); return getAll(url, paging, null, expectedStatus);
} }
protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams, int expectedStatus) throws Exception protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams,
int expectedStatus) throws Exception
{ {
Map<String, String> params = createParams(paging, otherParams); Map<String, String> params = createParams(paging, otherParams);
@@ -355,7 +348,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getAll(Class<?> entityResource, PublicApiClient.Paging paging, Map<String, String> otherParams, int expectedStatus) throws Exception protected HttpResponse getAll(Class<?> entityResource, PublicApiClient.Paging paging,
Map<String, String> otherParams, int expectedStatus) throws Exception
{ {
HttpResponse response = publicApiClient.get(entityResource, null, null, otherParams); HttpResponse response = publicApiClient.get(entityResource, null, null, otherParams);
checkStatus(expectedStatus, response.getStatusCode()); checkStatus(expectedStatus, response.getStatusCode());
@@ -363,16 +357,17 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams, Map<String, String> headers, int expectedStatus) throws Exception protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams,
Map<String, String> headers, int expectedStatus) throws Exception
{ {
return getAll(url, paging, otherParams, headers, null, expectedStatus); return getAll(url, paging, otherParams, headers, null, expectedStatus);
} }
protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams, Map<String, String> headers, String apiName, int expectedStatus) throws Exception protected HttpResponse getAll(String url, PublicApiClient.Paging paging, Map<String, String> otherParams,
Map<String, String> headers, String apiName, int expectedStatus) throws Exception
{ {
Map<String, String> params = createParams(paging, otherParams); Map<String, String> params = createParams(paging, otherParams);
RequestBuilder requestBuilder = httpClient.new GetRequestBuilder() RequestBuilder requestBuilder = httpClient.new GetRequestBuilder().setRequestContext(publicApiClient.getRequestContext())
.setRequestContext(publicApiClient.getRequestContext())
.setScope(getScope()) .setScope(getScope())
.setApiName(apiName) .setApiName(apiName)
.setEntityCollectionName(url) .setEntityCollectionName(url)
@@ -384,7 +379,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getSingle(String url, String entityId, int expectedStatus) throws Exception protected HttpResponse getSingle(String url, String entityId, int expectedStatus) throws Exception
{ {
return getSingle(url, entityId, null, expectedStatus); return getSingle(url, entityId, null, expectedStatus);
@@ -398,7 +393,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getSingle(String url, String entityId, Map<String, String> params, int expectedStatus) throws Exception protected HttpResponse getSingle(String url, String entityId, Map<String, String> params, int expectedStatus)
throws Exception
{ {
HttpResponse response = publicApiClient.get(getScope(), url, entityId, null, null, params); HttpResponse response = publicApiClient.get(getScope(), url, entityId, null, null, params);
checkStatus(expectedStatus, response.getStatusCode()); checkStatus(expectedStatus, response.getStatusCode());
@@ -406,7 +402,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getSingle(Class<?> entityResource, String entityId, Map<String, String> params, int expectedStatus) throws Exception protected HttpResponse getSingle(Class<?> entityResource, String entityId, Map<String, String> params,
int expectedStatus) throws Exception
{ {
HttpResponse response = publicApiClient.get(entityResource, entityId, null, params); HttpResponse response = publicApiClient.get(entityResource, entityId, null, params);
checkStatus(expectedStatus, response.getStatusCode()); checkStatus(expectedStatus, response.getStatusCode());
@@ -414,15 +411,16 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse getSingle(String url, String entityId, Map<String, String> params, Map<String, String> headers, int expectedStatus) throws Exception protected HttpResponse getSingle(String url, String entityId, Map<String, String> params,
Map<String, String> headers, int expectedStatus) throws Exception
{ {
return getSingle(url, entityId, params, headers, null, expectedStatus); return getSingle(url, entityId, params, headers, null, expectedStatus);
} }
protected HttpResponse getSingle(String url, String entityId, Map<String, String> params, Map<String, String> headers, String apiName, int expectedStatus) throws Exception protected HttpResponse getSingle(String url, String entityId, Map<String, String> params,
Map<String, String> headers, String apiName, int expectedStatus) throws Exception
{ {
RequestBuilder requestBuilder = httpClient.new GetRequestBuilder() RequestBuilder requestBuilder = httpClient.new GetRequestBuilder().setRequestContext(publicApiClient.getRequestContext())
.setRequestContext(publicApiClient.getRequestContext())
.setScope(getScope()) .setScope(getScope())
.setApiName(apiName) .setApiName(apiName)
.setEntityCollectionName(url) .setEntityCollectionName(url)
@@ -437,7 +435,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
protected HttpResponse getSingleWithDelayRetry(String url, String entityId, Map<String, String> params, protected HttpResponse getSingleWithDelayRetry(String url, String entityId, Map<String, String> params,
Map<String, String> headers, int repeat, long pauseInMillisecond, int expectedStatus) throws Exception Map<String, String> headers, int repeat, long pauseInMillisecond,
int expectedStatus) throws Exception
{ {
int retryCount = 0; int retryCount = 0;
while (retryCount < repeat) while (retryCount < repeat)
@@ -445,7 +444,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
try try
{ {
return getSingle(url, entityId, params, headers, expectedStatus); return getSingle(url, entityId, params, headers, expectedStatus);
} }
catch (AssertionError ex) catch (AssertionError ex)
{ {
retryCount++; retryCount++;
@@ -455,7 +454,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return null; return null;
} }
protected HttpResponse put(String url, String entityId, String body, String queryString, int expectedStatus) throws Exception protected HttpResponse put(String url, String entityId, String body, String queryString, int expectedStatus)
throws Exception
{ {
if (queryString != null) if (queryString != null)
{ {
@@ -467,8 +467,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return response; return response;
} }
protected HttpResponse putBinary(String url, int version, BinaryPayload payload, String queryString, Map<String, String> params, protected HttpResponse putBinary(String url, int version, BinaryPayload payload, String queryString,
int expectedStatus) throws Exception Map<String, String> params, int expectedStatus) throws Exception
{ {
if (queryString != null) if (queryString != null)
{ {
@@ -482,7 +482,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
protected HttpResponse putBinary(String url, BinaryPayload payload, String queryString, Map<String, String> params, protected HttpResponse putBinary(String url, BinaryPayload payload, String queryString, Map<String, String> params,
int expectedStatus) throws Exception int expectedStatus) throws Exception
{ {
return putBinary(url, 1, payload, queryString, params, expectedStatus); return putBinary(url, 1, payload, queryString, params, expectedStatus);
} }
@@ -492,18 +492,19 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return delete(url, entityId, null, expectedStatus); return delete(url, entityId, null, expectedStatus);
} }
protected HttpResponse delete(String url, String entityId, Map<String, String> params, int expectedStatus) throws Exception protected HttpResponse delete(String url, String entityId, Map<String, String> params, int expectedStatus)
throws Exception
{ {
HttpResponse response = publicApiClient.delete(getScope(), 1, url, entityId, null, null, params); HttpResponse response = publicApiClient.delete(getScope(), 1, url, entityId, null, null, params);
checkStatus(expectedStatus, response.getStatusCode()); checkStatus(expectedStatus, response.getStatusCode());
return response; return response;
} }
protected HttpResponse delete(String url, String entityId, Map<String, String> params, Map<String, String> headers, String apiName, int expectedStatus) throws Exception protected HttpResponse delete(String url, String entityId, Map<String, String> params, Map<String, String> headers,
String apiName, int expectedStatus) throws Exception
{ {
RequestBuilder requestBuilder = httpClient.new DeleteRequestBuilder() RequestBuilder requestBuilder = httpClient.new DeleteRequestBuilder().setRequestContext(publicApiClient.getRequestContext())
.setRequestContext(publicApiClient.getRequestContext())
.setScope(getScope()) .setScope(getScope())
.setApiName(apiName) .setApiName(apiName)
.setEntityCollectionName(url) .setEntityCollectionName(url)
@@ -524,7 +525,10 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String createUser(String usernameIn, String password, TestNetwork network) protected String createUser(String usernameIn, String password, TestNetwork network)
{ {
return createUser(new PersonInfo(usernameIn, usernameIn, usernameIn, password, null, null, null, null, null, null, null), network); return createUser(
new PersonInfo(usernameIn, usernameIn, usernameIn, password, null, null, null, null, null, null,
null),
network);
} }
/** /**
@@ -533,17 +537,16 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String createUser(final PersonInfo personInfo, final TestNetwork network) protected String createUser(final PersonInfo personInfo, final TestNetwork network)
{ {
final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN); final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN);
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() {
{
@Override @Override
public String doWork() throws Exception public String doWork() throws Exception
{ {
return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() {
{
public String doWork() throws Exception public String doWork() throws Exception
{ {
String username = repoService.getPublicApiContext().createUserName(personInfo.getUsername(), tenantDomain); String username = repoService.getPublicApiContext()
.createUserName(personInfo.getUsername(), tenantDomain);
personInfo.setUsername(username); personInfo.setUsername(username);
RepoService.TestPerson person = repoService.createUser(personInfo, username, network); RepoService.TestPerson person = repoService.createUser(personInfo, username, network);
return person.getId(); return person.getId();
@@ -561,17 +564,17 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{ {
final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN); final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN);
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() {
{
@Override @Override
public String doWork() throws Exception public String doWork() throws Exception
{ {
return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() {
{
public String doWork() throws Exception public String doWork() throws Exception
{ {
String username = repoService.getPublicApiContext().createUserName(usernameIn, tenantDomain); String username = repoService.getPublicApiContext()
PersonInfo personInfo = new PersonInfo(username, username, username, password, null, null, null, null, null, null, null); .createUserName(usernameIn, tenantDomain);
PersonInfo personInfo = new PersonInfo(username, username, username, password, null, null, null, null, null,
null, null);
RepoService.TestPerson person = repoService.getOrCreateUser(personInfo, username, network); RepoService.TestPerson person = repoService.getOrCreateUser(personInfo, username, network);
return person.getId(); return person.getId();
} }
@@ -587,13 +590,11 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{ {
final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN); final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN);
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() {
{
@Override @Override
public String doWork() throws Exception public String doWork() throws Exception
{ {
return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<String>() {
{
public String doWork() throws Exception public String doWork() throws Exception
{ {
repoService.deleteUser(username, network); repoService.deleteUser(username, network);
@@ -603,13 +604,15 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
}, networkAdmin); }, networkAdmin);
} }
protected SiteMember addSiteMember(String siteId, String userId, final SiteRole siteRole) throws Exception protected SiteMember addSiteMember(String siteId, String userId, final SiteRole siteRole) throws Exception
{ {
SiteMember siteMember = new SiteMember(userId, siteRole.name()); SiteMember siteMember = new SiteMember(userId, siteRole.name());
HttpResponse response = publicApiClient.post(getScope(), "sites", siteId, "members", null, siteMember.toJSON().toString()); HttpResponse response = publicApiClient.post(getScope(), "sites", siteId, "members", null, siteMember.toJSON()
.toString());
checkStatus(201, response.getStatusCode()); checkStatus(201, response.getStatusCode());
return SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); return SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject) response.getJsonResponse()
.get("entry"));
} }
protected Site createSite(String siteTitle, SiteVisibility siteVisibility) throws Exception protected Site createSite(String siteTitle, SiteVisibility siteVisibility) throws Exception
@@ -617,7 +620,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return createSite(null, siteTitle, null, siteVisibility, 201); return createSite(null, siteTitle, null, siteVisibility, 201);
} }
protected Site createSite(String siteId, String siteTitle, String siteDescription, SiteVisibility siteVisibility, int expectedStatus) throws Exception protected Site createSite(String siteId, String siteTitle, String siteDescription, SiteVisibility siteVisibility,
int expectedStatus) throws Exception
{ {
Site site = new Site(); Site site = new Site();
site.setId(siteId); site.setId(siteId);
@@ -633,7 +637,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected HttpResponse deleteSite(String siteId, boolean permanent, int expectedStatus) throws Exception protected HttpResponse deleteSite(String siteId, boolean permanent, int expectedStatus) throws Exception
{ {
Map params = null; Map params = null;
if (permanent == true) if (permanent)
{ {
params = Collections.singletonMap("permanent", "true"); params = Collections.singletonMap("permanent", "true");
} }
@@ -655,14 +659,14 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String getSiteContainerNodeId(String siteId, String containerNameId) throws Exception protected String getSiteContainerNodeId(String siteId, String containerNameId) throws Exception
{ {
Map<String, String> params = Collections.singletonMap(Nodes.PARAM_RELATIVE_PATH, "/Sites/" + siteId + "/" + containerNameId); Map<String, String> params = Collections.singletonMap(Nodes.PARAM_RELATIVE_PATH, "/Sites/" + siteId + "/" + containerNameId);
HttpResponse response = publicApiClient.get(NodesEntityResource.class, Nodes.PATH_ROOT, null, params); HttpResponse response = publicApiClient.get(NodesEntityResource.class, Nodes.PATH_ROOT, null, params);
checkStatus(200, response.getStatusCode()); checkStatus(200, response.getStatusCode());
Node node = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); Node node = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class);
return node.getId(); return node.getId();
} }
protected void checkStatus(int expectedStatus, int actualStatus) protected void checkStatus(int expectedStatus, int actualStatus)
{ {
if (expectedStatus > 0 && expectedStatus != actualStatus) if (expectedStatus > 0 && expectedStatus != actualStatus)
@@ -672,9 +676,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
/** /**
* @deprecated
*
* @param runAsUser * @param runAsUser
* @deprecated
*/ */
protected void setRequestContext(String runAsUser) protected void setRequestContext(String runAsUser)
{ {
@@ -702,9 +705,9 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
} }
else if ((runAsUser != null) && runAsUser.equals(DEFAULT_ADMIN)) else if ((runAsUser != null) && runAsUser.equals(DEFAULT_ADMIN))
{ {
runAsUser = runAsUser+"@"+runAsNetwork; runAsUser = runAsUser + "@" + runAsNetwork;
} }
publicApiClient.setRequestContext(new RequestContext(runAsNetwork, runAsUser, password)); publicApiClient.setRequestContext(new RequestContext(runAsNetwork, runAsUser, password));
} }
@@ -736,7 +739,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{ {
return createFolder(parentId, folderName, null); return createFolder(parentId, folderName, null);
} }
protected Folder createFolder(String parentId, String folderName, Map<String, Object> props) throws Exception protected Folder createFolder(String parentId, String folderName, Map<String, Object> props) throws Exception
{ {
return createNode(parentId, folderName, TYPE_CM_FOLDER, props, Folder.class); return createNode(parentId, folderName, TYPE_CM_FOLDER, props, Folder.class);
@@ -750,17 +753,18 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String createUniqueContent(String folderId) throws Exception protected String createUniqueContent(String folderId) throws Exception
{ {
Document documentResp = createTextFile(folderId, "file-" + System.currentTimeMillis(), Document documentResp = createTextFile(folderId, "file-" + System.currentTimeMillis(),
"some text-" + System.currentTimeMillis(), "UTF-8", null); "some text-" + System.currentTimeMillis(), "UTF-8", null);
return documentResp.getId(); return documentResp.getId();
} }
protected Node createNode(String parentId, String nodeName, String nodeType, Map<String, Object> props) throws Exception protected Node createNode(String parentId, String nodeName, String nodeType, Map<String, Object> props)
throws Exception
{ {
return createNode(parentId, nodeName, nodeType, props, Node.class); return createNode(parentId, nodeName, nodeType, props, Node.class);
} }
protected <T> T createNode(String parentId, String nodeName, String nodeType, Map<String, Object> props, Class<T> returnType) protected <T> T createNode(String parentId, String nodeName, String nodeType, Map<String, Object> props,
throws Exception Class<T> returnType) throws Exception
{ {
Node n = new Node(); Node n = new Node();
n.setName(nodeName); n.setName(nodeName);
@@ -772,7 +776,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return RestApiUtil.parseRestApiEntry(response.getJsonResponse(), returnType); return RestApiUtil.parseRestApiEntry(response.getJsonResponse(), returnType);
} }
protected void deleteNode(String nodeId) throws Exception protected void deleteNode(String nodeId) throws Exception
{ {
deleteNode(nodeId, 204); deleteNode(nodeId, 204);
@@ -786,25 +790,27 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected void deleteNode(String nodeId, boolean permanent, int expectedStatus) throws Exception protected void deleteNode(String nodeId, boolean permanent, int expectedStatus) throws Exception
{ {
Map params = null; Map params = null;
if (permanent == true) if (permanent)
{ {
params = Collections.singletonMap("permanent", "true"); params = Collections.singletonMap("permanent", "true");
} }
delete(URL_NODES, nodeId, params, expectedStatus); delete(URL_NODES, nodeId, params, expectedStatus);
} }
protected Document createTextFile(String parentId, String fileName, String textContent) throws IOException, Exception protected Document createTextFile(String parentId, String fileName, String textContent) throws Exception
{ {
return createTextFile(parentId, fileName, textContent, "UTF-8", null); return createTextFile(parentId, fileName, textContent, "UTF-8", null);
} }
protected Document createTextFile(String parentId, String fileName, String textContent, String encoding, Map<String, String> props) throws IOException, Exception protected Document createTextFile(String parentId, String fileName, String textContent, String encoding,
Map<String, String> props) throws Exception
{ {
return createTextFile(parentId, fileName, textContent, encoding, props, 201); return createTextFile(parentId, fileName, textContent, encoding, props, 201);
} }
protected Document createTextFile(String parentId, String fileName, String textContent, String encoding, Map<String, String> props, int expectedStatus) throws IOException, Exception protected Document createTextFile(String parentId, String fileName, String textContent, String encoding,
Map<String, String> props, int expectedStatus) throws Exception
{ {
if (props == null) if (props == null)
{ {
@@ -820,9 +826,11 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
.setProperties(props) .setProperties(props)
.build(); .build();
HttpResponse response = post(getNodeChildrenUrl(parentId), reqBody.getBody(), null, reqBody.getContentType(), expectedStatus); HttpResponse response = post(getNodeChildrenUrl(parentId), reqBody.getBody(), null, reqBody.getContentType(),
expectedStatus);
if (response.getJsonResponse().get("error") != null) if (response.getJsonResponse()
.get("error") != null)
{ {
return null; return null;
} }
@@ -834,8 +842,9 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{ {
return createEmptyTextFile(parentFolderId, docName, null, 201); return createEmptyTextFile(parentFolderId, docName, null, 201);
} }
protected Document createEmptyTextFile(String parentFolderId, String docName, Map<String, String> params, int expectedStatus) throws Exception protected Document createEmptyTextFile(String parentFolderId, String docName, Map<String, String> params,
int expectedStatus) throws Exception
{ {
Document d1 = new Document(); Document d1 = new Document();
d1.setName(docName); d1.setName(docName);
@@ -845,7 +854,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
d1.setContent(ci); d1.setContent(ci);
// create empty file // create empty file
HttpResponse response = post(getNodeChildrenUrl(parentFolderId), toJsonAsStringNonNull(d1), params, null, "alfresco", expectedStatus); HttpResponse response = post(getNodeChildrenUrl(parentFolderId), toJsonAsStringNonNull(d1), params, null, "alfresco",
expectedStatus);
if (expectedStatus != 201) if (expectedStatus != 201)
{ {
return null; return null;
@@ -858,7 +868,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return updateTextFile(contentId, textContent, params, 200); return updateTextFile(contentId, textContent, params, 200);
} }
protected Document updateTextFile(String contentId, String textContent, Map<String, String> params, int expectedStatus) throws Exception protected Document updateTextFile(String contentId, String textContent, Map<String, String> params,
int expectedStatus) throws Exception
{ {
ByteArrayInputStream inputStream = new ByteArrayInputStream(textContent.getBytes()); ByteArrayInputStream inputStream = new ByteArrayInputStream(textContent.getBytes());
File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt"); File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt");
@@ -874,7 +885,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected File getResourceFile(String fileName) throws FileNotFoundException protected File getResourceFile(String fileName) throws FileNotFoundException
{ {
URL url = NodeApiTest.class.getClassLoader().getResource(RESOURCE_PREFIX + fileName); URL url = NodeApiTest.class.getClassLoader()
.getResource(RESOURCE_PREFIX + fileName);
if (url == null) if (url == null)
{ {
fail("Cannot get the resource: " + fileName); fail("Cannot get the resource: " + fileName);
@@ -907,14 +919,15 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
* @return * @return
* @throws Exception * @throws Exception
*/ */
protected String updateFileVersions(String userId, String contentNodeId, int cnt, protected String updateFileVersions(String userId, String contentNodeId, int cnt, String textContentPrefix,
String textContentPrefix, int verCnt, int verCnt, Boolean majorVersion, String currentVersionLabel) throws Exception
Boolean majorVersion, String currentVersionLabel) throws Exception
{ {
String[] parts = currentVersionLabel.split("\\."); String[] parts = currentVersionLabel.split("\\.");
int majorVer = Integer.valueOf(parts[0]).intValue(); int majorVer = Integer.valueOf(parts[0])
int minorVer = Integer.valueOf(parts[1]).intValue(); .intValue();
int minorVer = Integer.valueOf(parts[1])
.intValue();
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put(Nodes.PARAM_OVERWRITE, "true"); params.put(Nodes.PARAM_OVERWRITE, "true");
@@ -928,7 +941,6 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
majorVersion = false; majorVersion = false;
} }
if (majorVersion) if (majorVersion)
{ {
minorVer = 0; minorVer = 0;
@@ -961,30 +973,33 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
HttpResponse response = putBinary(getNodeContentUrl(contentNodeId), payload, null, params, 200); HttpResponse response = putBinary(getNodeContentUrl(contentNodeId), payload, null, params, 200);
Node nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); Node nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class);
assertTrue(nodeResp.getAspectNames().contains("cm:versionable")); assertTrue(nodeResp.getAspectNames()
.contains("cm:versionable"));
assertNotNull(nodeResp.getProperties()); assertNotNull(nodeResp.getProperties());
assertEquals(currentVersionLabel, nodeResp.getProperties().get("cm:versionLabel")); assertEquals(currentVersionLabel, nodeResp.getProperties()
assertEquals((majorVersion ? "MAJOR" : "MINOR"), nodeResp.getProperties().get("cm:versionType")); .get("cm:versionLabel"));
assertEquals((majorVersion ? "MAJOR" : "MINOR"), nodeResp.getProperties()
.get("cm:versionType"));
// double-check - get version node info // double-check - get version node info
response = getSingle(getNodeVersionsUrl(contentNodeId), currentVersionLabel, null, 200); response = getSingle(getNodeVersionsUrl(contentNodeId), currentVersionLabel, null, 200);
nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class);
assertEquals(currentVersionLabel, nodeResp.getProperties().get("cm:versionLabel")); assertEquals(currentVersionLabel, nodeResp.getProperties()
assertEquals((majorVersion ? "MAJOR" : "MINOR"), nodeResp.getProperties().get("cm:versionType")); .get("cm:versionLabel"));
assertEquals((majorVersion ? "MAJOR" : "MINOR"), nodeResp.getProperties()
.get("cm:versionType"));
} }
return currentVersionLabel; return currentVersionLabel;
} }
protected static final long PAUSE_TIME = 5000; //millisecond
protected static final int MAX_RETRY = 20;
protected Rendition waitAndGetRendition(String sourceNodeId, String versionId, String renditionId) throws Exception protected Rendition waitAndGetRendition(String sourceNodeId, String versionId, String renditionId) throws Exception
{ {
return waitAndGetRendition(sourceNodeId, versionId, renditionId, MAX_RETRY, PAUSE_TIME); return waitAndGetRendition(sourceNodeId, versionId, renditionId, MAX_RETRY, PAUSE_TIME);
} }
protected Rendition waitAndGetRendition(String sourceNodeId, String versionId, String renditionId, int maxRetry, long pauseTime) throws Exception protected Rendition waitAndGetRendition(String sourceNodeId, String versionId, String renditionId, int maxRetry,
long pauseTime) throws Exception
{ {
int retryCount = 0; int retryCount = 0;
while (retryCount < maxRetry) while (retryCount < maxRetry)
@@ -992,7 +1007,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
try try
{ {
HttpResponse response; HttpResponse response;
if ((versionId != null) && (! versionId.isEmpty())) if ((versionId != null) && (!versionId.isEmpty()))
{ {
response = getSingle(getNodeVersionRenditionsUrl(sourceNodeId, versionId), renditionId, 200); response = getSingle(getNodeVersionRenditionsUrl(sourceNodeId, versionId), renditionId, 200);
} }
@@ -1011,7 +1026,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
// wait for 'PAUSE_TIME' and try again. // wait for 'PAUSE_TIME' and try again.
retryCount++; retryCount++;
System.out.println("waitAndGetRendition: "+retryCount); System.out.println("waitAndGetRendition: " + retryCount);
Thread.sleep(pauseTime); Thread.sleep(pauseTime);
} }
} }
@@ -1024,7 +1039,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return createAndGetRendition(sourceNodeId, null, renditionId); return createAndGetRendition(sourceNodeId, null, renditionId);
} }
protected Rendition createAndGetRendition(String sourceNodeId, String versionId, String renditionId) throws Exception protected Rendition createAndGetRendition(String sourceNodeId, String versionId, String renditionId)
throws Exception
{ {
Rendition renditionRequest = new Rendition(); Rendition renditionRequest = new Rendition();
renditionRequest.setId(renditionId); renditionRequest.setId(renditionId);
@@ -1035,9 +1051,10 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
try try
{ {
HttpResponse response; HttpResponse response;
if ((versionId != null) && (! versionId.isEmpty())) if ((versionId != null) && (!versionId.isEmpty()))
{ {
response = post(getNodeVersionRenditionsUrl(sourceNodeId, versionId), toJsonAsString(renditionRequest), 202); response = post(getNodeVersionRenditionsUrl(sourceNodeId, versionId),
toJsonAsString(renditionRequest), 202);
} }
else else
{ {
@@ -1052,7 +1069,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
// wait for 'PAUSE_TIME' and try again. // wait for 'PAUSE_TIME' and try again.
retryCount++; retryCount++;
System.out.println("waitAndGetRendition: "+retryCount); System.out.println("waitAndGetRendition: " + retryCount);
Thread.sleep(PAUSE_TIME); Thread.sleep(PAUSE_TIME);
} }
} }
@@ -1072,7 +1089,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
protected String getNodeVersionRenditionIdUrl(String nodeId, String versionId, String renditionID) protected String getNodeVersionRenditionIdUrl(String nodeId, String versionId, String renditionID)
{ {
return URL_NODES + "/" + nodeId + "/" + URL_VERSIONS + "/" + versionId + "/" + URL_RENDITIONS + "/" + renditionID; return URL_NODES + "/" + nodeId + "/" + URL_VERSIONS + "/" + versionId + "/" + URL_RENDITIONS + "/"
+ renditionID;
} }
protected String getNodeVersionsUrl(String nodeId) protected String getNodeVersionsUrl(String nodeId)
@@ -1120,5 +1138,14 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
RestApiDirectUrlConfig restDauConfig = (RestApiDirectUrlConfig) applicationContext.getBean("restApiDirectUrlConfig"); RestApiDirectUrlConfig restDauConfig = (RestApiDirectUrlConfig) applicationContext.getBean("restApiDirectUrlConfig");
restDauConfig.setEnabled(false); restDauConfig.setEnabled(false);
} }
}
protected String generateNodeSizeDetailsUrl(String nodeId)
{
return URL_NODES + "/" + nodeId + "/" + URL_CALCULATEFOLDERSIZE;
}
protected String getNodeSizeDetailsUrl(String nodeId, String jobId)
{
return URL_NODES + "/" + nodeId + "/" + URL_CALCULATEFOLDERSIZE + "/" + jobId;
}
}

View File

@@ -0,0 +1,41 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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
* 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.node.sizedetails;
import java.util.Optional;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails;
import org.alfresco.service.cmr.repository.NodeRef;
public interface NodeSizeDetailsService
{
void invokeSizeDetailsExecutor(NodeRef nodeRef, String jobId);
void putSizeDetails(String id, NodeSizeDetails nodeSizeDetails);
Optional<NodeSizeDetails> getSizeDetails(String id);
}

View File

@@ -0,0 +1,400 @@
/*
* #%L
* Alfresco Repository
* %%
* 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
* 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.node.sizedetails;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl.NodeSizeDetails.STATUS;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck;
/**
* NodeSizeDetailsServiceImpl Executing Alfresco FTS Query to find size details of Folder Node
*/
public class NodeSizeDetailsServiceImpl implements NodeSizeDetailsService, InitializingBean
{
private static final Logger LOG = LoggerFactory.getLogger(NodeSizeDetailsServiceImpl.class);
private static final String FIELD_FACET = "content.size";
private static final String FACET_QUERY = "{!afts}content.size:[0 TO " + Integer.MAX_VALUE + "]";
private SearchService searchService;
private SimpleCache<Serializable, NodeSizeDetails> simpleCache;
private TransactionService transactionService;
private ThreadPoolExecutor threadPoolExecutor;
private int defaultItems;
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
@Override
public Optional<NodeSizeDetails> getSizeDetails(String id)
{
NodeSizeDetails details = simpleCache.get(id);
return Optional.ofNullable(details)
.or(() -> {
LOG.error("No Size details found for ID: " + id);
return Optional.empty();
});
}
public void setSimpleCache(SimpleCache<Serializable, NodeSizeDetails> simpleCache)
{
this.simpleCache = simpleCache;
}
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
public void setThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor)
{
this.threadPoolExecutor = threadPoolExecutor;
}
public void setDefaultItems(int defaultItems)
{
this.defaultItems = defaultItems;
}
@Override
public void invokeSizeDetailsExecutor(NodeRef nodeRef, String jobId)
{
try
{
executeSizeCalculation(nodeRef, jobId);
}
catch (Exception e)
{
LOG.error("Exception occurred while executing invokeSizeDetailsExecutor method ", e);
}
}
@Override
public void putSizeDetails(String id, NodeSizeDetails nodeSizeDetails)
{
simpleCache.put(id, nodeSizeDetails);
}
private void executeSizeCalculation(NodeRef nodeRef, String jobId)
{
String authenticatedUserName = AuthenticationUtil.getFullyAuthenticatedUser();
RetryingTransactionCallback<NodeSizeDetails> executionCallback = () -> {
try
{
return calculateTotalSizeFromFacet(nodeRef, jobId);
}
catch (Exception ex)
{
LOG.error("Exception occurred in executeSizeCalculation:RetryingTransactionCallback ", ex);
throw ex;
}
};
threadPoolExecutor.execute(() -> {
NodeSizeDetails nodeSizeDetails = new NodeSizeDetails(nodeRef.getId(), jobId, STATUS.IN_PROGRESS);
putSizeDetails(nodeRef.getId(), nodeSizeDetails);
try
{
nodeSizeDetails = AuthenticationUtil.runAs(() -> transactionService.getRetryingTransactionHelper()
.doInTransaction(executionCallback, true), authenticatedUserName);
}
catch (Exception e)
{
LOG.error("Exception occurred in executeSizeCalculation", e);
nodeSizeDetails = new NodeSizeDetails(nodeRef.getId(), 0L, jobId, STATUS.FAILED);
}
finally
{
putSizeDetails(nodeRef.getId(), nodeSizeDetails);
}
});
}
private NodeSizeDetails calculateTotalSizeFromFacet(NodeRef nodeRef, String jobId)
{
long totalSizeFromFacet = 0;
int skipCount = 0;
int totalItems = defaultItems;
boolean isCalculationCompleted = false;
try
{
ResultSet results = facetQuery(nodeRef);
int resultsSize = results.getFieldFacet(FIELD_FACET)
.size();
while (!isCalculationCompleted)
{
List<Pair<String, Integer>> facetPairs = results.getFieldFacet(FIELD_FACET)
.subList(skipCount, Math.min(totalItems, resultsSize));
totalSizeFromFacet += facetPairs.parallelStream()
.mapToLong(pair -> Long.parseLong(pair.getFirst()) * pair.getSecond())
.sum();
if (resultsSize <= totalItems || resultsSize <= defaultItems)
{
isCalculationCompleted = true;
}
else
{
skipCount += defaultItems;
resultsSize -= totalItems;
totalItems += Math.min(resultsSize, defaultItems);
}
}
Date calculationDate = new Date(System.currentTimeMillis());
NodeSizeDetails nodeSizeDetails = new NodeSizeDetails(nodeRef.getId(), totalSizeFromFacet, calculationDate,
results.getNodeRefs()
.size(),
STATUS.COMPLETED, jobId);
return nodeSizeDetails;
}
catch (Exception e)
{
LOG.error("Exception occurred while calculating total size from facet", e);
throw e;
}
}
private ResultSet facetQuery(NodeRef nodeRef)
{
try
{
SearchParameters searchParameters = createSearchParameters(nodeRef);
ResultSet resultsWithoutFacet = searchService.query(searchParameters);
if (LOG.isDebugEnabled())
{
LOG.debug(" After Executing facet query, no. of records found " + resultsWithoutFacet.getNumberFound());
}
searchParameters.addFacetQuery(FACET_QUERY);
FieldFacet fieldFacet = new FieldFacet(FIELD_FACET);
fieldFacet.setLimitOrNull((int) resultsWithoutFacet.getNumberFound());
searchParameters.addFieldFacet(fieldFacet);
resultsWithoutFacet.close();
return searchService.query(searchParameters);
}
catch (Exception e)
{
LOG.error("Exception occurred while executing facetQuery ", e);
throw e;
}
}
private SearchParameters createSearchParameters(NodeRef nodeRef)
{
SearchParameters searchParameters = new SearchParameters();
searchParameters.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
searchParameters.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
searchParameters.setQuery("ANCESTOR:\"" + nodeRef + "\" AND TYPE:\"cm:content\"");
searchParameters.setTrackTotalHits(-1);
return searchParameters;
}
@Override
public void afterPropertiesSet() throws Exception
{
ParameterCheck.mandatory("searchService", this.searchService);
ParameterCheck.mandatory("simpleCache", this.simpleCache);
ParameterCheck.mandatory("transactionService", this.transactionService);
ParameterCheck.mandatory("threadPoolExecutor", this.threadPoolExecutor);
}
/**
* POJO class to hold node size details.
*/
public static class NodeSizeDetails implements Serializable
{
private static final long serialVersionUID = 1L;
private String id;
private Long sizeInBytes;
private Date calculatedAt;
private Integer numberOfFiles;
private String jobId;
private STATUS status;
public NodeSizeDetails()
{}
public NodeSizeDetails(String jobId)
{
this.jobId = jobId;
}
public NodeSizeDetails(String id, STATUS status)
{
this.id = id;
this.status = status;
}
public NodeSizeDetails(String id, String jobId, STATUS status)
{
this.id = id;
this.jobId = jobId;
this.status = status;
}
public NodeSizeDetails(String id, Long sizeInBytes, String jobId, STATUS status)
{
this.id = id;
this.sizeInBytes = sizeInBytes;
this.jobId = jobId;
this.status = status;
}
public NodeSizeDetails(String id, Long sizeInBytes, Date calculatedAt, Integer numberOfFiles,
STATUS currentStatus, String jobId)
{
this.id = id;
this.sizeInBytes = sizeInBytes;
this.calculatedAt = calculatedAt;
this.numberOfFiles = numberOfFiles;
this.status = currentStatus;
this.jobId = jobId;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public Long getSizeInBytes()
{
return sizeInBytes;
}
public void setSizeInBytes(Long sizeInBytes)
{
this.sizeInBytes = sizeInBytes;
}
public Date getCalculatedAt()
{
return calculatedAt;
}
public void setCalculatedAt(Date calculatedAt)
{
this.calculatedAt = calculatedAt;
}
public Integer getNumberOfFiles()
{
return numberOfFiles;
}
public void setNumberOfFiles(Integer numberOfFiles)
{
this.numberOfFiles = numberOfFiles;
}
public String getJobId()
{
return jobId;
}
public void setJobId(String jobId)
{
this.jobId = jobId;
}
public STATUS getStatus()
{
return status;
}
public void setStatus(STATUS status)
{
this.status = status;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
NodeSizeDetails that = (NodeSizeDetails) o;
return Objects.equals(id, that.id) && Objects.equals(sizeInBytes, that.sizeInBytes) && Objects.equals(
calculatedAt, that.calculatedAt) && Objects.equals(numberOfFiles, that.numberOfFiles)
&& Objects.equals(jobId, that.jobId) && status == that.status;
}
@Override
public int hashCode()
{
return Objects.hash(id, sizeInBytes, calculatedAt, numberOfFiles, jobId, status);
}
@Override
public String toString()
{
return "NodeSizeDetails{" + "id='" + id + '\'' + ", sizeInBytes=" + sizeInBytes + ", calculatedAt="
+ calculatedAt + ", numberOfFiles=" + numberOfFiles + ", jobId='" + jobId + '\'' + ", status="
+ status + '}';
}
public enum STATUS
{
NOT_INITIATED, PENDING, IN_PROGRESS, COMPLETED, FAILED
}
}
}

View File

@@ -514,4 +514,10 @@
<bean name="ldapInitialDirContextCache" factory-bean="cacheFactory" factory-method="createCache"> <bean name="ldapInitialDirContextCache" factory-bean="cacheFactory" factory-method="createCache">
<constructor-arg value="cache.ldapInitialDirContextCache"/> <constructor-arg value="cache.ldapInitialDirContextCache"/>
</bean> </bean>
<!-- The shared cache for Folder Node -->
<bean name="folderSizeSharedCache" factory-bean="cacheFactory" factory-method="createCache">
<constructor-arg value="cache.folderSizeSharedCache"/>
</bean>
</beans> </beans>

View File

@@ -710,3 +710,12 @@ cache.ldapInitialDirContextCache.backup-count=1
cache.ldapInitialDirContextCache.eviction-policy=NONE cache.ldapInitialDirContextCache.eviction-policy=NONE
cache.ldapInitialDirContextCache.merge-policy=com.hazelcast.spi.merge.LatestUpdateMergePolicy cache.ldapInitialDirContextCache.merge-policy=com.hazelcast.spi.merge.LatestUpdateMergePolicy
cache.ldapInitialDirContextCache.readBackupData=false cache.ldapInitialDirContextCache.readBackupData=false
cache.folderSizeSharedCache.maxItems=1000
cache.folderSizeSharedCache.timeToLiveSeconds=300
cache.folderSizeSharedCache.maxIdleSeconds=0
cache.folderSizeSharedCache.cluster.type=fully-distributed
cache.folderSizeSharedCache.backup-count=1
cache.folderSizeSharedCache.eviction-policy=LRU
cache.folderSizeSharedCache.merge-policy=com.hazelcast.spi.merge.PutIfAbsentMergePolicy
cache.folderSizeSharedCache.readBackupData=false

View File

@@ -330,6 +330,42 @@
<property name="nodeService" ref="nodeService"/> <property name="nodeService" ref="nodeService"/>
<property name="policyComponent" ref="policyComponent"/> <property name="policyComponent" ref="policyComponent"/>
<property name="searchTrackingComponent" ref="searchTrackingComponent" /> <property name="searchTrackingComponent" ref="searchTrackingComponent" />
</bean> </bean>
<bean id="nodeSizeThreadPool" class="org.alfresco.util.ThreadPoolExecutorFactoryBean">
<property name="poolName">
<value>defaultThreadPool</value>
</property>
<property name="corePoolSize">
<value>${default.nodeSize.corePoolSize}</value>
</property>
<property name="maximumPoolSize">
<value>${default.nodeSize.maximumPoolSize}</value>
</property>
<property name="workQueueSize">
<value>${default.nodeSize.workQueueSize}</value>
</property>
</bean>
<bean id="NodeSizeDetailsServiceImpl" class="org.alfresco.repo.node.sizedetails.NodeSizeDetailsServiceImpl">
<property name="searchService" ref="SearchService"/>
<property name="simpleCache" ref="folderSizeSharedCache" />
<property name="transactionService" ref="transactionService"/>
<property name="threadPoolExecutor">
<ref bean="nodeSizeThreadPool"/>
</property>
<property name="defaultItems" value="${default.async.folder.items}"/>
</bean>
<bean id="NodeSizeDetailsService" class="org.springframework.aop.framework.ProxyFactoryBean" >
<property name="targetName">
<value>NodeSizeDetailsServiceImpl</value>
</property>
<property name="proxyInterfaces">
<list>
<value>org.alfresco.repo.node.sizedetails.NodeSizeDetailsService</value>
</list>
</property>
</bean>
</beans> </beans>

View File

@@ -1385,3 +1385,12 @@ scripts.execution.maxMemoryUsedInBytes=-1
# Number of instructions that will trigger the observer # Number of instructions that will trigger the observer
scripts.execution.observerInstructionCount=5000 scripts.execution.observerInstructionCount=5000
# Default value being used in POST/size-details endpoint to partition a huge folder into smaller chunks
# so that we can compute more efficiently and consolidate all sizes into a single unit.
default.async.folder.items=1000
# Default NodeSize Thread pool
default.nodeSize.corePoolSize=5
default.nodeSize.maximumPoolSize=10
default.nodeSize.workQueueSize=100