mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
17 Commits
fix/MNT-24
...
18.6
Author | SHA1 | Date | |
---|---|---|---|
|
4d930a6f18 | ||
|
ff68f92455 | ||
|
c88353ccb7 | ||
|
6b94ee41d4 | ||
|
a414aa3064 | ||
|
7914e87f77 | ||
|
4f63b3871e | ||
|
876962db57 | ||
|
5e2ff120ae | ||
|
2d95ccc754 | ||
|
3de741a78e | ||
|
8993ec9d5c | ||
|
428a82c195 | ||
|
519ef19c83 | ||
|
f19849b547 | ||
|
d956a4f4aa | ||
|
71f649d1bd |
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
# Version label
|
# Version label
|
||||||
version.major=7
|
version.major=7
|
||||||
version.minor=3
|
version.minor=3
|
||||||
version.revision=0
|
version.revision=1
|
||||||
version.label=
|
version.label=
|
||||||
|
|
||||||
# Edition label
|
# Edition label
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
6
pom.xml
6
pom.xml
@@ -2,7 +2,7 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Alfresco Community Repo Parent</name>
|
<name>Alfresco Community Repo Parent</name>
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<acs.version.major>7</acs.version.major>
|
<acs.version.major>7</acs.version.major>
|
||||||
<acs.version.minor>3</acs.version.minor>
|
<acs.version.minor>3</acs.version.minor>
|
||||||
<acs.version.revision>0</acs.version.revision>
|
<acs.version.revision>1</acs.version.revision>
|
||||||
<acs.version.label />
|
<acs.version.label />
|
||||||
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||||
<tag>17.183</tag>
|
<tag>18.6</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -295,7 +295,18 @@ public class AuditImpl implements Audit
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
totalItems = hasMoreItems ? getAuditEntriesCountByApp(auditApplication) : totalRetrievedItems;
|
if (hasMoreItems) {
|
||||||
|
if (q != null) {
|
||||||
|
// filtering via "where" clause
|
||||||
|
AuditEntryQueryWalker propertyWalker = new AuditEntryQueryWalker();
|
||||||
|
QueryHelper.walk(q, propertyWalker);
|
||||||
|
totalItems = getAuditEntriesCountByAppAndProperties(auditApplication, propertyWalker);
|
||||||
|
} else {
|
||||||
|
totalItems = getAuditEntriesCountByApp(auditApplication);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
totalItems = totalRetrievedItems;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entriesAudit = (skipCount >= totalRetrievedItems)
|
entriesAudit = (skipCount >= totalRetrievedItems)
|
||||||
@@ -895,4 +906,19 @@ public class AuditImpl implements Audit
|
|||||||
final String applicationName = auditApplication.getKey().substring(1);
|
final String applicationName = auditApplication.getKey().substring(1);
|
||||||
return auditService.getAuditEntriesCountByApp(applicationName);
|
return auditService.getAuditEntriesCountByApp(applicationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker)
|
||||||
|
{
|
||||||
|
final String applicationName = auditApplication.getKey().substring(1);
|
||||||
|
|
||||||
|
AuditQueryParameters parameters = new AuditQueryParameters();
|
||||||
|
parameters.setApplicationName(applicationName);
|
||||||
|
parameters.setFromTime(propertyWalker.getFromTime());
|
||||||
|
parameters.setToTime(propertyWalker.getToTime());
|
||||||
|
parameters.setFromId(propertyWalker.getFromId());
|
||||||
|
parameters.setToId(propertyWalker.getToId());
|
||||||
|
parameters.setUser(propertyWalker.getCreatedByUser());
|
||||||
|
|
||||||
|
return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,13 @@ function main()
|
|||||||
// Get the args
|
// Get the args
|
||||||
var siteShortName = url.templateArgs.shortname,
|
var siteShortName = url.templateArgs.shortname,
|
||||||
site = siteService.getSite(siteShortName),
|
site = siteService.getSite(siteShortName),
|
||||||
filter = ((args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "" )+ " [hint:useCQ]",
|
|
||||||
maxResults = (args.maxResults == null) ? 10 : parseInt(args.maxResults, 10),
|
maxResults = (args.maxResults == null) ? 10 : parseInt(args.maxResults, 10),
|
||||||
authorityType = args.authorityType,
|
authorityType = args.authorityType,
|
||||||
zone = args.zone,
|
zone = args.zone,
|
||||||
sortBy = args.sortBy,
|
sortBy = args.sortBy,
|
||||||
sortAsc = args.dir != "desc";
|
sortAsc = args.dir != "desc";
|
||||||
|
|
||||||
|
var filter;
|
||||||
|
|
||||||
|
|
||||||
if (authorityType != null)
|
if (authorityType != null)
|
||||||
@@ -28,6 +29,7 @@ function main()
|
|||||||
|
|
||||||
if (authorityType == null || authorityType == "USER")
|
if (authorityType == null || authorityType == "USER")
|
||||||
{
|
{
|
||||||
|
filter = ((args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "" )+ " [hint:useCQ]";
|
||||||
// Get the collection of people
|
// Get the collection of people
|
||||||
peopleFound = sortBy != null ? people.getPeople(filter, maxResults, sortBy, sortAsc) : people.getPeople(filter, maxResults);
|
peopleFound = sortBy != null ? people.getPeople(filter, maxResults, sortBy, sortAsc) : people.getPeople(filter, maxResults);
|
||||||
|
|
||||||
@@ -67,6 +69,7 @@ function main()
|
|||||||
|
|
||||||
if (authorityType == null || authorityType == "GROUP")
|
if (authorityType == null || authorityType == "GROUP")
|
||||||
{
|
{
|
||||||
|
filter = (args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "";
|
||||||
// Get the collection of groups
|
// Get the collection of groups
|
||||||
paging = utils.createPaging(maxResults, -1);
|
paging = utils.createPaging(maxResults, -1);
|
||||||
groupsFound = groups.getGroupsInZone(filter, zone, paging, "displayName");
|
groupsFound = groups.getGroupsInZone(filter, zone, paging, "displayName");
|
||||||
@@ -96,4 +99,4 @@ function contains(arr, value) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
@@ -34,6 +34,9 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -386,6 +389,7 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest
|
|||||||
AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access");
|
AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access");
|
||||||
|
|
||||||
testGetAuditEntries(auditAppsProxy, auditApp);
|
testGetAuditEntries(auditAppsProxy, auditApp);
|
||||||
|
testGetAuditEntriesWhereCreatedAt(auditAppsProxy, auditApp);
|
||||||
testAuditEntriesSorting(auditAppsProxy, auditApp);
|
testAuditEntriesSorting(auditAppsProxy, auditApp);
|
||||||
testAuditEntriesWhereDate(auditAppsProxy, auditApp);
|
testAuditEntriesWhereDate(auditAppsProxy, auditApp);
|
||||||
testAuditEntriesWhereId(auditAppsProxy, auditApp);
|
testAuditEntriesWhereId(auditAppsProxy, auditApp);
|
||||||
@@ -396,6 +400,30 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest
|
|||||||
testDeleteAuditEntries(auditAppsProxy, auditApp);
|
testDeleteAuditEntries(auditAppsProxy, auditApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testGetAuditEntriesWhereCreatedAt(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception
|
||||||
|
{
|
||||||
|
// get "totalItems" for a specific time interval
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
|
||||||
|
final ZonedDateTime beginDate = ZonedDateTime.now().minusHours(1).truncatedTo(ChronoUnit.MINUTES);
|
||||||
|
final ZonedDateTime endDate = ZonedDateTime.now().truncatedTo(ChronoUnit.MINUTES);
|
||||||
|
params.put("where","(createdAt BETWEEN ('"+beginDate.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)+"' , '"+endDate.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)+"'))");
|
||||||
|
|
||||||
|
ListResponse<AuditEntry> auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), params,
|
||||||
|
HttpServletResponse.SC_OK);
|
||||||
|
int totalItemsWithDefaultMaxSize = auditEntries.getPaging().getTotalItems();
|
||||||
|
assertTrue( totalItemsWithDefaultMaxSize > 1 );
|
||||||
|
|
||||||
|
// get "totalItems" for a specific time internal (with maxSize=1)
|
||||||
|
params.put("maxSize","1");
|
||||||
|
auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), params,
|
||||||
|
HttpServletResponse.SC_OK);
|
||||||
|
int totalItemsWithMaxSize1 = auditEntries.getPaging().getTotalItems();
|
||||||
|
|
||||||
|
// number of "totalItems" must be the same, regardless maxSize
|
||||||
|
assertEquals(totalItemsWithMaxSize1, totalItemsWithDefaultMaxSize);
|
||||||
|
}
|
||||||
|
|
||||||
private void testGetAuditEntries(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception
|
private void testGetAuditEntries(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception
|
||||||
{
|
{
|
||||||
// Positive tests
|
// Positive tests
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>17.183</version>
|
<version>18.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -272,4 +272,16 @@ public interface AuditComponent
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue an audit query to retrieve count of records for a given application and properties
|
||||||
|
*
|
||||||
|
* @param applicationName the name of the application
|
||||||
|
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
|
||||||
|
* @return a map containing min/max and the associated value
|
||||||
|
*/
|
||||||
|
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -955,4 +955,11 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
|
|
||||||
return auditDAO.getAuditEntriesCountByApp(applicationId);
|
return auditDAO.getAuditEntriesCountByApp(applicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
org.alfresco.repo.domain.audit.AuditQueryParameters dbParameters = new org.alfresco.repo.domain.audit.AuditQueryParameters();
|
||||||
|
|
||||||
|
return auditDAO.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -186,4 +186,12 @@ public class AuditServiceImpl implements AuditService
|
|||||||
{
|
{
|
||||||
return auditComponent.getAuditEntriesCountByApp(applicationName);
|
return auditComponent.getAuditEntriesCountByApp(applicationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -25,6 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.content.transform;
|
package org.alfresco.repo.content.transform;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
@@ -44,9 +48,6 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
|||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client class that transfers content (from a ContentReader) to a remote transformation agent together with
|
* Client class that transfers content (from a ContentReader) to a remote transformation agent together with
|
||||||
* request parameters that will be used to transform the content. The transformed content is then returned and
|
* request parameters that will be used to transform the content. The transformed content is then returned and
|
||||||
@@ -86,44 +87,33 @@ public class RemoteTransformerClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void request(ContentReader reader, ContentWriter writer, String sourceMimetype, String sourceExtension,
|
public void request(ContentReader reader, ContentWriter writer, String sourceMimetype, String sourceExtension,
|
||||||
String targetExtension, long timeoutMs, Log logger, String... args)
|
String targetExtension, long timeoutMs, Log logger, String... args)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (args.length % 2 != 0)
|
if (args.length % 2 != 0)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("There should be a value for each request property");
|
throw new IllegalArgumentException("There should be a value for each request property");
|
||||||
}
|
}
|
||||||
|
|
||||||
StringJoiner sj = new StringJoiner(" ");
|
StringJoiner sj = new StringJoiner(" ");
|
||||||
HttpEntity reqEntity = getRequestEntity(reader, sourceMimetype, sourceExtension, targetExtension, timeoutMs, args, sj);
|
|
||||||
|
|
||||||
request(logger, sourceExtension, targetExtension, reqEntity, writer, sj.toString());
|
try (InputStream contentStream = reader.getContentInputStream())
|
||||||
|
{
|
||||||
|
HttpEntity reqEntity = getRequestEntity(contentStream, sourceMimetype, sourceExtension, targetExtension, timeoutMs,
|
||||||
|
args, sj);
|
||||||
|
|
||||||
|
request(logger, sourceExtension, targetExtension, reqEntity, writer, sj.toString());
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to read content from reader", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpEntity getRequestEntity(ContentReader reader, String sourceMimetype, String sourceExtension,
|
HttpEntity getRequestEntity(ContentReader reader, String sourceMimetype, String sourceExtension, String targetExtension,
|
||||||
String targetExtension, long timeoutMs, String[] args, StringJoiner sj)
|
long timeoutMs, String[] args, StringJoiner sj)
|
||||||
{
|
{
|
||||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
return getRequestEntity(reader.getContentInputStream(), sourceMimetype, sourceExtension, targetExtension, timeoutMs, args, sj);
|
||||||
ContentType contentType = ContentType.create(sourceMimetype);
|
|
||||||
builder.addBinaryBody("file", reader.getContentInputStream(), contentType, "tmp."+sourceExtension);
|
|
||||||
builder.addTextBody("targetExtension", targetExtension);
|
|
||||||
sj.add("targetExtension" + '=' + targetExtension);
|
|
||||||
for (int i=0; i< args.length; i+=2)
|
|
||||||
{
|
|
||||||
if (args[i+1] != null)
|
|
||||||
{
|
|
||||||
builder.addTextBody(args[i], args[i + 1]);
|
|
||||||
|
|
||||||
sj.add(args[i] + '=' + args[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeoutMs > 0)
|
|
||||||
{
|
|
||||||
String timeoutMsString = Long.toString(timeoutMs);
|
|
||||||
builder.addTextBody("timeout", timeoutMsString);
|
|
||||||
sj.add("timeout=" + timeoutMsString);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void request(Log logger, String sourceExtension, String targetExtension, HttpEntity reqEntity, ContentWriter writer, String args)
|
void request(Log logger, String sourceExtension, String targetExtension, HttpEntity reqEntity, ContentWriter writer, String args)
|
||||||
@@ -331,6 +321,33 @@ public class RemoteTransformerClient
|
|||||||
return httpclient.execute(httpGet);
|
return httpclient.execute(httpGet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HttpEntity getRequestEntity(InputStream contentStream, String sourceMimetype, String sourceExtension,
|
||||||
|
String targetExtension, long timeoutMs, String[] args, StringJoiner sj)
|
||||||
|
{
|
||||||
|
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
|
ContentType contentType = ContentType.create(sourceMimetype);
|
||||||
|
builder.addBinaryBody("file", contentStream, contentType, "tmp." + sourceExtension);
|
||||||
|
builder.addTextBody("targetExtension", targetExtension);
|
||||||
|
sj.add("targetExtension" + '=' + targetExtension);
|
||||||
|
for (int i = 0; i < args.length; i += 2)
|
||||||
|
{
|
||||||
|
if (args[i + 1] != null)
|
||||||
|
{
|
||||||
|
builder.addTextBody(args[i], args[i + 1]);
|
||||||
|
|
||||||
|
sj.add(args[i] + '=' + args[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeoutMs > 0)
|
||||||
|
{
|
||||||
|
String timeoutMsString = Long.toString(timeoutMs);
|
||||||
|
builder.addTextBody("timeout", timeoutMsString);
|
||||||
|
sj.add("timeout=" + timeoutMsString);
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
// Strip out just the error message in the response
|
// Strip out just the error message in the response
|
||||||
private String getErrorMessage(HttpEntity resEntity) throws IOException
|
private String getErrorMessage(HttpEntity resEntity) throws IOException
|
||||||
{
|
{
|
||||||
|
@@ -1,28 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 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.repo.domain.audit;
|
package org.alfresco.repo.domain.audit;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -452,37 +452,86 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
org.alfresco.service.cmr.audit.AuditQueryParameters parameters,
|
org.alfresco.service.cmr.audit.AuditQueryParameters parameters,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
{
|
{
|
||||||
String searchKey = null;
|
|
||||||
Serializable searchValue = null;
|
|
||||||
if (parameters.getSearchKeyValues().size() > 0)
|
|
||||||
{
|
|
||||||
// Only handle one pair for now
|
|
||||||
Pair<String, Serializable> searchKeyValue = parameters.getSearchKeyValues().get(0);
|
|
||||||
searchKey = searchKeyValue.getFirst();
|
|
||||||
searchValue = searchKeyValue.getSecond();
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
||||||
findAuditEntries(
|
findAuditEntries(
|
||||||
rowHandler,
|
rowHandler,
|
||||||
parameters.isForward(),
|
|
||||||
parameters.getApplicationName(),
|
|
||||||
parameters.getUser(),
|
|
||||||
parameters.getFromId(),
|
|
||||||
parameters.getToId(),
|
|
||||||
parameters.getFromTime(),
|
|
||||||
parameters.getToTime(),
|
|
||||||
maxResults,
|
maxResults,
|
||||||
searchKey,
|
parameters);
|
||||||
searchValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void findAuditEntries(
|
protected abstract void findAuditEntries(
|
||||||
AuditQueryRowHandler rowHandler,
|
AuditQueryRowHandler rowHandler,
|
||||||
boolean forward,
|
|
||||||
String applicationName, String user,
|
|
||||||
Long fromId, Long toId,
|
|
||||||
Long fromTime, Long toTime,
|
|
||||||
int maxResults,
|
int maxResults,
|
||||||
String searchKey, Serializable searchValue);
|
org.alfresco.service.cmr.audit.AuditQueryParameters restParameters);
|
||||||
|
|
||||||
|
protected AuditQueryParameters convertFromRestAuditQueryParameters(org.alfresco.service.cmr.audit.AuditQueryParameters restParameters)
|
||||||
|
{
|
||||||
|
AuditQueryParameters dbParameters = new AuditQueryParameters();
|
||||||
|
|
||||||
|
String appName = restParameters.getApplicationName();
|
||||||
|
if (appName != null)
|
||||||
|
{
|
||||||
|
// Look up the application's ID (this is unique)
|
||||||
|
Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName);
|
||||||
|
if (appNamePair == null)
|
||||||
|
{
|
||||||
|
// No such value
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
dbParameters.setAuditAppNameId(appNamePair.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
String user = restParameters.getUser();
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
// Look up the application's ID (this is unique)
|
||||||
|
Pair<Long, Serializable> userPair = propertyValueDAO.getPropertyValue(user);
|
||||||
|
if (userPair == null)
|
||||||
|
{
|
||||||
|
// No such value
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
dbParameters.setAuditUserId(userPair.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
dbParameters.setAuditFromId(restParameters.getFromId());
|
||||||
|
dbParameters.setAuditToId(restParameters.getToId());
|
||||||
|
dbParameters.setAuditFromTime(restParameters.getFromTime());
|
||||||
|
dbParameters.setAuditToTime(restParameters.getToTime());
|
||||||
|
|
||||||
|
String searchKey = null;
|
||||||
|
Serializable searchValue = null;
|
||||||
|
if (restParameters.getSearchKeyValues().size() > 0)
|
||||||
|
{
|
||||||
|
// Only handle one pair for now
|
||||||
|
Pair<String, Serializable> searchKeyValue = restParameters.getSearchKeyValues().get(0);
|
||||||
|
searchKey = searchKeyValue.getFirst();
|
||||||
|
searchValue = searchKeyValue.getSecond();
|
||||||
|
}
|
||||||
|
if (searchKey != null)
|
||||||
|
{
|
||||||
|
// Look up the ID of the search key
|
||||||
|
Pair<Long, Serializable> searchKeyPair = propertyValueDAO.getPropertyValue(searchKey);
|
||||||
|
if (searchKeyPair == null)
|
||||||
|
{
|
||||||
|
// No such value
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
dbParameters.setSearchKeyId(searchKeyPair.getFirst());
|
||||||
|
}
|
||||||
|
if (searchValue != null)
|
||||||
|
{
|
||||||
|
// Look up the ID of the search key
|
||||||
|
Pair<Long, Serializable> searchValuePair = propertyValueDAO.getPropertyValue(searchValue);
|
||||||
|
if (searchValuePair == null)
|
||||||
|
{
|
||||||
|
// No such value
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
dbParameters.setSearchValueId(searchValuePair.getFirst());
|
||||||
|
}
|
||||||
|
dbParameters.setForward(restParameters.isForward());
|
||||||
|
|
||||||
|
return dbParameters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -244,4 +244,16 @@ public interface AuditDAO
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue an audit query to retrieve count of records for a given application and properties
|
||||||
|
*
|
||||||
|
* @param applicationName name of the application to be queried
|
||||||
|
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
|
||||||
|
* @return a map containing min/max and the associated value
|
||||||
|
*/
|
||||||
|
default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -66,6 +66,7 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry";
|
private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry";
|
||||||
private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId";
|
private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId";
|
||||||
private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId";
|
private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId";
|
||||||
|
private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause";
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple";
|
private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple";
|
||||||
@@ -235,68 +236,29 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters);
|
||||||
|
|
||||||
|
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected void findAuditEntries(
|
protected void findAuditEntries(
|
||||||
final AuditQueryRowHandler rowHandler,
|
final AuditQueryRowHandler rowHandler,
|
||||||
boolean forward,
|
|
||||||
String appName, String user,
|
|
||||||
Long fromId, Long toId,
|
|
||||||
Long fromTime, Long toTime,
|
|
||||||
int maxResults,
|
int maxResults,
|
||||||
String searchKey, Serializable searchValue)
|
org.alfresco.service.cmr.audit.AuditQueryParameters restParameters)
|
||||||
{
|
{
|
||||||
AuditQueryParameters params = new AuditQueryParameters();
|
AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters);
|
||||||
if (appName != null)
|
if (params==null)
|
||||||
{
|
{
|
||||||
// Look up the application's ID (this is unique)
|
return;
|
||||||
Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName);
|
|
||||||
if (appNamePair == null)
|
|
||||||
{
|
|
||||||
// No such value
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
params.setAuditAppNameId(appNamePair.getFirst());
|
|
||||||
}
|
}
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
// Look up the application's ID (this is unique)
|
|
||||||
Pair<Long, Serializable> userPair = propertyValueDAO.getPropertyValue(user);
|
|
||||||
if (userPair == null)
|
|
||||||
{
|
|
||||||
// No such value
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
params.setAuditUserId(userPair.getFirst());
|
|
||||||
}
|
|
||||||
params.setAuditFromId(fromId);
|
|
||||||
params.setAuditToId(toId);
|
|
||||||
params.setAuditFromTime(fromTime);
|
|
||||||
params.setAuditToTime(toTime);
|
|
||||||
if (searchKey != null)
|
|
||||||
{
|
|
||||||
// Look up the ID of the search key
|
|
||||||
Pair<Long, Serializable> searchKeyPair = propertyValueDAO.getPropertyValue(searchKey);
|
|
||||||
if (searchKeyPair == null)
|
|
||||||
{
|
|
||||||
// No such value
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
params.setSearchKeyId(searchKeyPair.getFirst());
|
|
||||||
}
|
|
||||||
if (searchValue != null)
|
|
||||||
{
|
|
||||||
// Look up the ID of the search key
|
|
||||||
Pair<Long, Serializable> searchValuePair = propertyValueDAO.getPropertyValue(searchValue);
|
|
||||||
if (searchValuePair == null)
|
|
||||||
{
|
|
||||||
// No such value
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
params.setSearchValueId(searchValuePair.getFirst());
|
|
||||||
}
|
|
||||||
params.setForward(forward);
|
|
||||||
|
|
||||||
if (maxResults > 0)
|
if (maxResults > 0)
|
||||||
{
|
{
|
||||||
// Query without getting the values. We gather all the results and batch-fetch the audited
|
// Query without getting the values. We gather all the results and batch-fetch the audited
|
||||||
|
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2022 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.jscript;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.mozilla.javascript.Callable;
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.ContextFactory;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom factory that allows to apply configured limits during script executions
|
||||||
|
*
|
||||||
|
* @see ContextFactory
|
||||||
|
*/
|
||||||
|
public class AlfrescoContextFactory extends ContextFactory
|
||||||
|
{
|
||||||
|
private static final Log LOGGER = LogFactory.getLog(AlfrescoContextFactory.class);
|
||||||
|
|
||||||
|
private int optimizationLevel = -1;
|
||||||
|
private int maxScriptExecutionSeconds = -1;
|
||||||
|
private int maxStackDepth = -1;
|
||||||
|
private long maxMemoryUsedInBytes = -1L;
|
||||||
|
private int observeInstructionCount = -1;
|
||||||
|
|
||||||
|
private AlfrescoScriptThreadMxBeanWrapper threadMxBeanWrapper;
|
||||||
|
|
||||||
|
private final int INTERPRETIVE_MODE = -1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Context makeContext()
|
||||||
|
{
|
||||||
|
AlfrescoScriptContext context = new AlfrescoScriptContext();
|
||||||
|
|
||||||
|
context.setOptimizationLevel(optimizationLevel);
|
||||||
|
|
||||||
|
// Needed for both time and memory measurement
|
||||||
|
if (maxScriptExecutionSeconds > 0 || maxMemoryUsedInBytes > 0L)
|
||||||
|
{
|
||||||
|
if (observeInstructionCount > 0)
|
||||||
|
{
|
||||||
|
LOGGER.info("Enabling observer count...");
|
||||||
|
context.setGenerateObserverCount(true);
|
||||||
|
context.setInstructionObserverThreshold(observeInstructionCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.info("Disabling observer count...");
|
||||||
|
context.setGenerateObserverCount(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory limit
|
||||||
|
if (maxMemoryUsedInBytes > 0)
|
||||||
|
{
|
||||||
|
context.setThreadId(Thread.currentThread().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max stack depth
|
||||||
|
if (maxStackDepth > 0)
|
||||||
|
{
|
||||||
|
if (optimizationLevel != INTERPRETIVE_MODE)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Changing optimization level from " + optimizationLevel + " to " + INTERPRETIVE_MODE);
|
||||||
|
}
|
||||||
|
// stack depth can only be set when no optimizations are applied
|
||||||
|
context.setOptimizationLevel(INTERPRETIVE_MODE);
|
||||||
|
context.setMaximumInterpreterStackDepth(maxStackDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void observeInstructionCount(Context cx, int instructionCount)
|
||||||
|
{
|
||||||
|
AlfrescoScriptContext acx = (AlfrescoScriptContext) cx;
|
||||||
|
|
||||||
|
if (acx.isLimitsEnabled())
|
||||||
|
{
|
||||||
|
// Time limit
|
||||||
|
if (maxScriptExecutionSeconds > 0)
|
||||||
|
{
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (currentTime - acx.getStartTime() > maxScriptExecutionSeconds * 1000)
|
||||||
|
{
|
||||||
|
throw new Error("Maximum script time of " + maxScriptExecutionSeconds + " seconds exceeded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
if (maxMemoryUsedInBytes > 0 && threadMxBeanWrapper != null && threadMxBeanWrapper.isThreadAllocatedMemorySupported())
|
||||||
|
{
|
||||||
|
|
||||||
|
if (acx.getStartMemory() <= 0)
|
||||||
|
{
|
||||||
|
acx.setStartMemory(threadMxBeanWrapper.getThreadAllocatedBytes(acx.getThreadId()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long currentAllocatedBytes = threadMxBeanWrapper.getThreadAllocatedBytes(acx.getThreadId());
|
||||||
|
if (currentAllocatedBytes - acx.getStartMemory() >= maxMemoryUsedInBytes)
|
||||||
|
{
|
||||||
|
throw new Error("Memory limit of " + maxMemoryUsedInBytes + " bytes reached");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args)
|
||||||
|
{
|
||||||
|
AlfrescoScriptContext acx = (AlfrescoScriptContext) cx;
|
||||||
|
acx.setStartTime(System.currentTimeMillis());
|
||||||
|
return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOptimizationLevel()
|
||||||
|
{
|
||||||
|
return optimizationLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptimizationLevel(int optimizationLevel)
|
||||||
|
{
|
||||||
|
this.optimizationLevel = optimizationLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxScriptExecutionSeconds()
|
||||||
|
{
|
||||||
|
return maxScriptExecutionSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxScriptExecutionSeconds(int maxScriptExecutionSeconds)
|
||||||
|
{
|
||||||
|
this.maxScriptExecutionSeconds = maxScriptExecutionSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxStackDepth()
|
||||||
|
{
|
||||||
|
return maxStackDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxStackDepth(int maxStackDepth)
|
||||||
|
{
|
||||||
|
this.maxStackDepth = maxStackDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMaxMemoryUsedInBytes()
|
||||||
|
{
|
||||||
|
return maxMemoryUsedInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxMemoryUsedInBytes(long maxMemoryUsedInBytes)
|
||||||
|
{
|
||||||
|
this.maxMemoryUsedInBytes = maxMemoryUsedInBytes;
|
||||||
|
if (maxMemoryUsedInBytes > 0)
|
||||||
|
{
|
||||||
|
this.threadMxBeanWrapper = new AlfrescoScriptThreadMxBeanWrapper();
|
||||||
|
if (!threadMxBeanWrapper.isThreadAllocatedMemorySupported())
|
||||||
|
{
|
||||||
|
LOGGER.warn("com.sun.management.ThreadMXBean was not found on the classpath. "
|
||||||
|
+ "This means that the limiting the memory usage for a script will NOT work.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getObserveInstructionCount()
|
||||||
|
{
|
||||||
|
return observeInstructionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObserveInstructionCount(int observeInstructionCount)
|
||||||
|
{
|
||||||
|
this.observeInstructionCount = observeInstructionCount;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2022 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.jscript;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Rhino context that holds data as start time and memory
|
||||||
|
*
|
||||||
|
* @see Context
|
||||||
|
*/
|
||||||
|
public class AlfrescoScriptContext extends Context
|
||||||
|
{
|
||||||
|
private long startTime;
|
||||||
|
private long threadId;
|
||||||
|
private long startMemory;
|
||||||
|
private boolean limitsEnabled = false;
|
||||||
|
|
||||||
|
public long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(long startTime)
|
||||||
|
{
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getThreadId()
|
||||||
|
{
|
||||||
|
return threadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThreadId(long threadId)
|
||||||
|
{
|
||||||
|
this.threadId = threadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartMemory()
|
||||||
|
{
|
||||||
|
return startMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartMemory(long startMemory)
|
||||||
|
{
|
||||||
|
this.startMemory = startMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLimitsEnabled()
|
||||||
|
{
|
||||||
|
return limitsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLimitsEnabled(boolean limitsEnabled)
|
||||||
|
{
|
||||||
|
this.limitsEnabled = limitsEnabled;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2022 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.jscript;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to monitor memory usage
|
||||||
|
*/
|
||||||
|
public class AlfrescoScriptThreadMxBeanWrapper
|
||||||
|
{
|
||||||
|
|
||||||
|
private ThreadMXBean threadMXBean = null;
|
||||||
|
private boolean threadAllocatedMemorySupported = false;
|
||||||
|
|
||||||
|
private final String THREAD_MX_BEAN_SUN = "com.sun.management.ThreadMXBean";
|
||||||
|
|
||||||
|
public AlfrescoScriptThreadMxBeanWrapper()
|
||||||
|
{
|
||||||
|
checkThreadAllocatedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getThreadAllocatedBytes(long threadId)
|
||||||
|
{
|
||||||
|
if (threadMXBean != null && threadAllocatedMemorySupported)
|
||||||
|
{
|
||||||
|
return ((com.sun.management.ThreadMXBean) threadMXBean).getThreadAllocatedBytes(threadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkThreadAllocatedMemory()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class<?> clazz = Class.forName(THREAD_MX_BEAN_SUN);
|
||||||
|
if (clazz != null)
|
||||||
|
{
|
||||||
|
this.threadAllocatedMemorySupported = true;
|
||||||
|
this.threadMXBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.threadAllocatedMemorySupported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThreadAllocatedMemorySupported()
|
||||||
|
{
|
||||||
|
return threadAllocatedMemorySupported;
|
||||||
|
}
|
||||||
|
}
|
@@ -57,10 +57,12 @@ import org.alfresco.service.namespace.QName;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.ContextFactory;
|
||||||
import org.mozilla.javascript.ImporterTopLevel;
|
import org.mozilla.javascript.ImporterTopLevel;
|
||||||
import org.mozilla.javascript.Script;
|
import org.mozilla.javascript.Script;
|
||||||
import org.mozilla.javascript.Scriptable;
|
import org.mozilla.javascript.Scriptable;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
import org.mozilla.javascript.Undefined;
|
||||||
import org.mozilla.javascript.WrapFactory;
|
import org.mozilla.javascript.WrapFactory;
|
||||||
import org.mozilla.javascript.WrappedException;
|
import org.mozilla.javascript.WrappedException;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@@ -108,7 +110,24 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
/** Cache of runtime compiled script instances */
|
/** Cache of runtime compiled script instances */
|
||||||
private final Map<String, Script> scriptCache = new ConcurrentHashMap<String, Script>(256);
|
private final Map<String, Script> scriptCache = new ConcurrentHashMap<String, Script>(256);
|
||||||
|
|
||||||
|
/** Rhino optimization level */
|
||||||
|
private int optimizationLevel = -1;
|
||||||
|
|
||||||
|
/** Maximum seconds a script is allowed to run */
|
||||||
|
private int maxScriptExecutionSeconds = -1;
|
||||||
|
|
||||||
|
/** Maximum of call stack depth (in terms of number of call frames) */
|
||||||
|
private int maxStackDepth = -1;
|
||||||
|
|
||||||
|
/** Maximum memory (bytes) a script can use */
|
||||||
|
private long maxMemoryUsedInBytes = -1L;
|
||||||
|
|
||||||
|
/** Number of (bytecode) instructions that will trigger the observer */
|
||||||
|
private int observerInstructionCount = 100;
|
||||||
|
|
||||||
|
/** Custom context factory */
|
||||||
|
public static AlfrescoContextFactory contextFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default store reference
|
* Set the default store reference
|
||||||
*
|
*
|
||||||
@@ -143,6 +162,51 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
{
|
{
|
||||||
this.shareSealedScopes = shareSealedScopes;
|
this.shareSealedScopes = shareSealedScopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param optimizationLevel
|
||||||
|
* -1 interpretive mode, 0 no optimizations, 1-9 optimizations performed
|
||||||
|
*/
|
||||||
|
public void setOptimizationLevel(int optimizationLevel)
|
||||||
|
{
|
||||||
|
this.optimizationLevel = optimizationLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxScriptExecutionSeconds
|
||||||
|
* the number of seconds a script is allowed to run
|
||||||
|
*/
|
||||||
|
public void setMaxScriptExecutionSeconds(int maxScriptExecutionSeconds)
|
||||||
|
{
|
||||||
|
this.maxScriptExecutionSeconds = maxScriptExecutionSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxStackDepth
|
||||||
|
* the number of call stack depth allowed
|
||||||
|
*/
|
||||||
|
public void setMaxStackDepth(int maxStackDepth)
|
||||||
|
{
|
||||||
|
this.maxStackDepth = maxStackDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxMemoryUsedInBytes
|
||||||
|
* the number of memory a script can use
|
||||||
|
*/
|
||||||
|
public void setMaxMemoryUsedInBytes(long maxMemoryUsedInBytes)
|
||||||
|
{
|
||||||
|
this.maxMemoryUsedInBytes = maxMemoryUsedInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param observerInstructionCount
|
||||||
|
* the number of instructions that will trigger {@link ContextFactory#observeInstructionCount}
|
||||||
|
*/
|
||||||
|
public void setObserverInstructionCount(int observerInstructionCount)
|
||||||
|
{
|
||||||
|
this.observerInstructionCount = observerInstructionCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.service.cmr.repository.ScriptProcessor#reset()
|
* @see org.alfresco.service.cmr.repository.ScriptProcessor#reset()
|
||||||
@@ -449,6 +513,8 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
private Object executeScriptImpl(Script script, Map<String, Object> model, boolean secure, String debugScriptName)
|
private Object executeScriptImpl(Script script, Map<String, Object> model, boolean secure, String debugScriptName)
|
||||||
throws AlfrescoRuntimeException
|
throws AlfrescoRuntimeException
|
||||||
{
|
{
|
||||||
|
Scriptable scope = null;
|
||||||
|
|
||||||
long startTime = 0;
|
long startTime = 0;
|
||||||
if (callLogger.isDebugEnabled())
|
if (callLogger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
@@ -465,14 +531,16 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
// Create a thread-specific scope from one of the shared scopes.
|
// Create a thread-specific scope from one of the shared scopes.
|
||||||
// See http://www.mozilla.org/rhino/scopes.html
|
// See http://www.mozilla.org/rhino/scopes.html
|
||||||
cx.setWrapFactory(secure ? wrapFactory : sandboxFactory);
|
cx.setWrapFactory(secure ? wrapFactory : sandboxFactory);
|
||||||
Scriptable scope;
|
|
||||||
|
// Enables or disables execution limits based on secure flag
|
||||||
|
enableLimits(cx, secure);
|
||||||
|
|
||||||
if (this.shareSealedScopes)
|
if (this.shareSealedScopes)
|
||||||
{
|
{
|
||||||
Scriptable sharedScope = secure ? this.nonSecureScope : this.secureScope;
|
Scriptable sharedScope = secure ? this.nonSecureScope : this.secureScope;
|
||||||
scope = cx.newObject(sharedScope);
|
scope = cx.newObject(sharedScope);
|
||||||
scope.setPrototype(sharedScope);
|
scope.setPrototype(sharedScope);
|
||||||
scope.setParentScope(null);
|
scope.setParentScope(null);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -545,7 +613,8 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
throw new AlfrescoRuntimeException(err.getMessage(), err);
|
throw new AlfrescoRuntimeException(err.getMessage(), err);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
unsetScope(model, scope);
|
||||||
Context.exit();
|
Context.exit();
|
||||||
|
|
||||||
if (callLogger.isDebugEnabled())
|
if (callLogger.isDebugEnabled())
|
||||||
@@ -638,6 +707,9 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
*/
|
*/
|
||||||
public void afterPropertiesSet() throws Exception
|
public void afterPropertiesSet() throws Exception
|
||||||
{
|
{
|
||||||
|
// Initialize context factory
|
||||||
|
initContextFactory();
|
||||||
|
|
||||||
// Initialize the secure scope
|
// Initialize the secure scope
|
||||||
Context cx = Context.enter();
|
Context cx = Context.enter();
|
||||||
try
|
try
|
||||||
@@ -695,4 +767,129 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
}
|
}
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean supplied scope and unset it from any model instance where it has been injected before
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
* Data model containing objects from where scope will be unset
|
||||||
|
* @param scope
|
||||||
|
* The scope to clean
|
||||||
|
*/
|
||||||
|
private void unsetScope(Map<String, Object> model, Scriptable scope)
|
||||||
|
{
|
||||||
|
if (scope != null)
|
||||||
|
{
|
||||||
|
Object[] ids = scope.getIds();
|
||||||
|
if (ids != null)
|
||||||
|
{
|
||||||
|
for (Object id : ids)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
deleteProperty(scope, id.toString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.info("Unable to delete id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model != null)
|
||||||
|
{
|
||||||
|
for (String key : model.keySet())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
deleteProperty(scope, key);
|
||||||
|
|
||||||
|
Object obj = model.get(key);
|
||||||
|
if (obj instanceof Scopeable)
|
||||||
|
{
|
||||||
|
((Scopeable) obj).setScope(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.info("Unable to unset model object " + key + " : ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a property from the supplied scope, if property is not removable, then is set to null
|
||||||
|
*
|
||||||
|
* @param scope
|
||||||
|
* the scope object from where property will be removed
|
||||||
|
* @param name
|
||||||
|
* the property name to delete
|
||||||
|
*/
|
||||||
|
private void deleteProperty(Scriptable scope, String name)
|
||||||
|
{
|
||||||
|
if (scope != null && name != null)
|
||||||
|
{
|
||||||
|
if (!ScriptableObject.deleteProperty(scope, name))
|
||||||
|
{
|
||||||
|
ScriptableObject.putProperty(scope, name, null);
|
||||||
|
}
|
||||||
|
scope.delete(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the context factory with limits configuration
|
||||||
|
*/
|
||||||
|
private synchronized void initContextFactory()
|
||||||
|
{
|
||||||
|
if (contextFactory == null)
|
||||||
|
{
|
||||||
|
contextFactory = new AlfrescoContextFactory();
|
||||||
|
contextFactory.setOptimizationLevel(optimizationLevel);
|
||||||
|
|
||||||
|
if (maxScriptExecutionSeconds > 0)
|
||||||
|
{
|
||||||
|
contextFactory.setMaxScriptExecutionSeconds(maxScriptExecutionSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxMemoryUsedInBytes > 0L)
|
||||||
|
{
|
||||||
|
contextFactory.setMaxMemoryUsedInBytes(maxMemoryUsedInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxStackDepth > 0)
|
||||||
|
{
|
||||||
|
contextFactory.setMaxStackDepth(maxStackDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxScriptExecutionSeconds > 0 || maxMemoryUsedInBytes > 0L)
|
||||||
|
{
|
||||||
|
contextFactory.setObserveInstructionCount(observerInstructionCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextFactory.initGlobal(contextFactory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If script is considered secure no limits will be applied, otherwise, the limits are enabled and the script can be
|
||||||
|
* interrupted in case a limit has been reached.
|
||||||
|
*
|
||||||
|
* @param cx
|
||||||
|
* the Rhino scope
|
||||||
|
* @param secure
|
||||||
|
* true if script execution is considered secure (e.g, deployed at classpath level)
|
||||||
|
*/
|
||||||
|
private void enableLimits(Context cx, boolean secure)
|
||||||
|
{
|
||||||
|
if (cx != null)
|
||||||
|
{
|
||||||
|
if (cx instanceof AlfrescoScriptContext)
|
||||||
|
{
|
||||||
|
((AlfrescoScriptContext) cx).setLimitsEnabled(!secure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -267,7 +267,11 @@ public class SolrJSONResultSet implements SearchEngineResultSet {
|
|||||||
ArrayList<Pair<String, Integer>> facetValues = new ArrayList<Pair<String, Integer>>(facetArraySize/2);
|
ArrayList<Pair<String, Integer>> facetValues = new ArrayList<Pair<String, Integer>>(facetArraySize/2);
|
||||||
for(int i = 0; i < facetArraySize; i+=2)
|
for(int i = 0; i < facetArraySize; i+=2)
|
||||||
{
|
{
|
||||||
String facetEntryName = facets.getString(i);
|
String facetEntryName = "Null";
|
||||||
|
if(!facets.isNull(i))
|
||||||
|
{
|
||||||
|
facetEntryName = facets.getString(i);
|
||||||
|
}
|
||||||
Integer facetEntryCount = Integer.valueOf(facets.getInt(i+1));
|
Integer facetEntryCount = Integer.valueOf(facets.getInt(i+1));
|
||||||
Pair<String, Integer> pair = new Pair<String, Integer>(facetEntryName, facetEntryCount);
|
Pair<String, Integer> pair = new Pair<String, Integer>(facetEntryName, facetEntryCount);
|
||||||
facetValues.add(pair);
|
facetValues.add(pair);
|
||||||
|
@@ -252,4 +252,16 @@ public interface AuditService
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue an audit query to retrieve min / max audit record id for a given application and properties
|
||||||
|
*
|
||||||
|
* @param applicationName the name of the application
|
||||||
|
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
|
||||||
|
* @return a map containing min/max and the associated value
|
||||||
|
*/
|
||||||
|
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,6 +50,15 @@
|
|||||||
<!-- Parameter Maps -->
|
<!-- Parameter Maps -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
|
<parameterMap id="parameter_AuditAppId_WhereClauseMap" type="map">
|
||||||
|
<parameter property="auditAppNameId" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
<parameter property="auditUserId" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
<parameter property="auditFromTime" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
<parameter property="auditToTime" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
<parameter property="auditFromId" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
<parameter property="auditToId" jdbcType="BIGINT" javaType="Long"/>
|
||||||
|
</parameterMap>
|
||||||
|
|
||||||
<parameterMap id="parameter_IdMap" type="map">
|
<parameterMap id="parameter_IdMap" type="map">
|
||||||
<parameter property="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<parameter property="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
</parameterMap>
|
</parameterMap>
|
||||||
@@ -291,6 +300,20 @@
|
|||||||
alf_audit_entry.audit_app_id = #{auditAppId}
|
alf_audit_entry.audit_app_id = #{auditAppId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="select_CountAuditEntryIdWithWhereClause" parameterMap="parameter_AuditAppId_WhereClauseMap" resultType="int">
|
||||||
|
select
|
||||||
|
COUNT(entry.id)
|
||||||
|
from
|
||||||
|
alf_audit_entry as entry
|
||||||
|
<if test="auditAppNameId != null">
|
||||||
|
join alf_audit_app app on (entry.audit_app_id = app.id)
|
||||||
|
</if>
|
||||||
|
<if test="keyOrValueSearch == true">
|
||||||
|
join alf_prop_link sp_pl on (sp_pl.root_prop_id = entry.audit_values_id)
|
||||||
|
</if>
|
||||||
|
<include refid="select_AuditEntriesWhereSnippet"/>
|
||||||
|
</select>
|
||||||
|
|
||||||
<!-- Get the maximum/minimum audit entry id for application -->
|
<!-- Get the maximum/minimum audit entry id for application -->
|
||||||
<select id="select_MinMaxAuditEntryId" parameterMap="parameter_IdMinMaxMap" resultMap="result_minMaxMap">
|
<select id="select_MinMaxAuditEntryId" parameterMap="parameter_IdMinMaxMap" resultMap="result_minMaxMap">
|
||||||
select
|
select
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
repository.name=Main Repository
|
repository.name=Main Repository
|
||||||
|
|
||||||
# Schema number
|
# Schema number
|
||||||
version.schema=17000
|
version.schema=17100
|
||||||
|
|
||||||
# Directory configuration
|
# Directory configuration
|
||||||
|
|
||||||
@@ -1351,3 +1351,18 @@ import.zip.compressionRatioThreshold=100
|
|||||||
# "zip bomb" and the import extraction process cancelled. No value (or a negative long) will be taken to mean that no
|
# "zip bomb" and the import extraction process cancelled. No value (or a negative long) will be taken to mean that no
|
||||||
# limit should be applied.
|
# limit should be applied.
|
||||||
import.zip.uncompressedBytesLimit=
|
import.zip.uncompressedBytesLimit=
|
||||||
|
|
||||||
|
# Rhino optimization level
|
||||||
|
scripts.execution.optimizationLevel=0
|
||||||
|
|
||||||
|
# Max seconds a script is allowed to run
|
||||||
|
scripts.execution.maxScriptExecutionSeconds=-1
|
||||||
|
|
||||||
|
# Max call stack depth
|
||||||
|
scripts.execution.maxStackDepth=-1
|
||||||
|
|
||||||
|
# Max memory (bytes) a script can use
|
||||||
|
scripts.execution.maxMemoryUsedInBytes=-1
|
||||||
|
|
||||||
|
# Number of instructions that will trigger the observer
|
||||||
|
scripts.execution.observerInstructionCount=-1
|
||||||
|
@@ -45,6 +45,21 @@
|
|||||||
<property name="storePath">
|
<property name="storePath">
|
||||||
<value>${spaces.company_home.childname}</value>
|
<value>${spaces.company_home.childname}</value>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="optimizationLevel">
|
||||||
|
<value>${scripts.execution.optimizationLevel}</value>
|
||||||
|
</property>
|
||||||
|
<property name="maxScriptExecutionSeconds">
|
||||||
|
<value>${scripts.execution.maxScriptExecutionSeconds}</value>
|
||||||
|
</property>
|
||||||
|
<property name="maxStackDepth">
|
||||||
|
<value>${scripts.execution.maxStackDepth}</value>
|
||||||
|
</property>
|
||||||
|
<property name="maxMemoryUsedInBytes">
|
||||||
|
<value>${scripts.execution.maxMemoryUsedInBytes}</value>
|
||||||
|
</property>
|
||||||
|
<property name="observerInstructionCount">
|
||||||
|
<value>${scripts.execution.observerInstructionCount}</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- base config implementation that script extension beans extend from - for auto registration
|
<!-- base config implementation that script extension beans extend from - for auto registration
|
||||||
|
@@ -44,7 +44,6 @@ import org.alfresco.service.cmr.repository.ContentService;
|
|||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.ScriptProcessor;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptService;
|
import org.alfresco.service.cmr.repository.ScriptService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -53,8 +52,11 @@ import org.alfresco.test_category.OwnJVMTestsCategory;
|
|||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.ImporterTopLevel;
|
||||||
import org.mozilla.javascript.Scriptable;
|
import org.mozilla.javascript.Scriptable;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
import org.mozilla.javascript.Undefined;
|
||||||
|
import org.mozilla.javascript.UniqueTag;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@@ -445,6 +447,67 @@ public class RhinoScriptTest extends TestCase
|
|||||||
assertTrue("Script should have been executed (secure = true)", executed);
|
assertTrue("Script should have been executed (secure = true)", executed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MNT-23158
|
||||||
|
public void testScopeData()
|
||||||
|
{
|
||||||
|
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||||
|
new RetryingTransactionCallback<Object>()
|
||||||
|
{
|
||||||
|
public Object execute() throws Exception
|
||||||
|
{
|
||||||
|
Context cx = Context.enter();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Scriptable sharedScope = new ImporterTopLevel(cx, true);
|
||||||
|
Scriptable scope = cx.newObject(sharedScope);
|
||||||
|
scope.setPrototype(sharedScope);
|
||||||
|
scope.setParentScope(null);
|
||||||
|
|
||||||
|
// Executes a first script
|
||||||
|
Object result = cx.evaluateString(scope, "var a = 10; var b = 20; var sum = a+b;", "TestJS1", 1, null);
|
||||||
|
assertTrue(Undefined.isUndefined(result));
|
||||||
|
|
||||||
|
// Test sum value
|
||||||
|
Object sum = scope.get("sum", scope);
|
||||||
|
assertEquals(30.0, Context.toNumber(sum));
|
||||||
|
|
||||||
|
// No 'sum' property should be found in the shared scope
|
||||||
|
sum = sharedScope.get("sum", sharedScope);
|
||||||
|
assertEquals(sum, UniqueTag.NOT_FOUND);
|
||||||
|
|
||||||
|
// No 'b' property should be found in the shared scope
|
||||||
|
Object b = ScriptableObject.getProperty(sharedScope, "b");
|
||||||
|
assertEquals(b, UniqueTag.NOT_FOUND);
|
||||||
|
|
||||||
|
// Cleans scope
|
||||||
|
unsetScope(scope);
|
||||||
|
|
||||||
|
// Executes a second script using the same scope
|
||||||
|
result = cx.evaluateString(scope, "var test = 'test';", "TestJS2", 1, null);
|
||||||
|
|
||||||
|
// 'sum' property should be null
|
||||||
|
sum = scope.get("sum", scope);
|
||||||
|
assertNull(sum);
|
||||||
|
|
||||||
|
// New scope initialization
|
||||||
|
scope = cx.newObject(sharedScope);
|
||||||
|
scope.setPrototype(sharedScope);
|
||||||
|
scope.setParentScope(null);
|
||||||
|
|
||||||
|
// check 'test' property
|
||||||
|
Object test = scope.get("test", scope);
|
||||||
|
assertEquals(test, UniqueTag.NOT_FOUND);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Context.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private boolean executeSecureScriptString(String script, Boolean secure)
|
private boolean executeSecureScriptString(String script, Boolean secure)
|
||||||
{
|
{
|
||||||
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Boolean>()
|
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Boolean>()
|
||||||
@@ -475,6 +538,41 @@ public class RhinoScriptTest extends TestCase
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void unsetScope(Scriptable scope)
|
||||||
|
{
|
||||||
|
if (scope != null)
|
||||||
|
{
|
||||||
|
Object[] ids = scope.getIds();
|
||||||
|
|
||||||
|
if (ids != null)
|
||||||
|
{
|
||||||
|
for (Object id : ids)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
deleteProperty(scope, id.toString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteProperty(Scriptable scope, String name)
|
||||||
|
{
|
||||||
|
if (scope != null && name != null)
|
||||||
|
{
|
||||||
|
if (!ScriptableObject.deleteProperty(scope, name))
|
||||||
|
{
|
||||||
|
ScriptableObject.putProperty(scope, name, null);
|
||||||
|
}
|
||||||
|
scope.delete(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final String TESTSCRIPT_CLASSPATH1 = "org/alfresco/repo/jscript/test_script1.js";
|
private static final String TESTSCRIPT_CLASSPATH1 = "org/alfresco/repo/jscript/test_script1.js";
|
||||||
private static final String TESTSCRIPT_CLASSPATH2 = "org/alfresco/repo/jscript/test_script2.js";
|
private static final String TESTSCRIPT_CLASSPATH2 = "org/alfresco/repo/jscript/test_script2.js";
|
||||||
|
Reference in New Issue
Block a user