diff --git a/AUTHORS b/AUTHORS
index 566d88618..28e89ca3e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -46,7 +46,7 @@ Written in 2015 by Sam Hamilton - samhamilton
Written in 2015 by Leonardo Carvalho - CarvalhoLeonardo
Written in 2015 by Swapnil M Mane - swapnilmmane
Written in 2015 by Anton Akhiar - akhiar
-Written in 2015-2018 by Jens Hardings - jenshp
+Written in 2015-2023 by Jens Hardings - jenshp
Written in 2016 by Shifeng Zhang - zhangshifeng
Written in 2016 by Scott Gray - lektran
Written in 2016 by Mark Haney - mphaney
@@ -54,12 +54,14 @@ Written in 2016 by Qiushi Yan - yanqiushi
Written in 2017 by Oleg Andrieiev - oandreyev
Written in 2018 by Zhang Wei - zhangwei1979
Written in 2018 by Nirendra Singh - nirendra10695
-Written in 2018-2021 by Ayman Abi Abdallah - aabiabdallah
+Written in 2018-2023 by Ayman Abi Abdallah - aabiabdallah
Written in 2019 by Daniel Taylor - danieltaylor-nz
Written in 2020 by Jacob Barnes - Tellan
Written in 2020 by Amir Anjomshoaa - amiranjom
Written in 2021 by Deepak Dixit - dixitdeepak
Written in 2021 by Taher Alkhateeb - pythys
+Written in 2022 by Zhang Wei - hellozhangwei
+Written in 2023 by Rohit Pawar - rohitpawar2811
===========================================================================
@@ -92,7 +94,7 @@ Written in 2015 by Jimmy Shen - shendepu
Written in 2015-2016 by Sam Hamilton - samhamilton
Written in 2015 by Leonardo Carvalho - CarvalhoLeonardo
Written in 2015 by Anton Akhiar - akhiar
-Written in 2015-2016 by Jens Hardings - jenshp
+Written in 2015-2023 by Jens Hardings - jenshp
Written in 2016 by Shifeng Zhang - zhangshifeng
Written in 2016 by Scott Gray - lektran
Written in 2016 by Mark Haney - mphaney
@@ -100,11 +102,13 @@ Written in 2016 by Qiushi Yan - yanqiushi
Written in 2017 by Oleg Andrieiev - oandreyev
Written in 2018 by Zhang Wei - zhangwei1979
Written in 2018 by Nirendra Singh - nirendra10695
-Written in 2018-2020 by Ayman Abi Abdallah - aabiabdallah
+Written in 2018-2023 by Ayman Abi Abdallah - aabiabdallah
Written in 2019 by Daniel Taylor - danieltaylor-nz
Written in 2020 by Jacob Barnes - Tellan
Written in 2020 by Amir Anjomshoaa - amiranjom
Written in 2021 by Deepak Dixit - dixitdeepak
Written in 2021 by Taher Alkhateeb - pythys
+Written in 2022 by Zhang Wei - hellozhangwei
+Written in 2023 by Rohit Pawar - rohitpawar2811
===========================================================================
diff --git a/addons.xml b/addons.xml
index e5a926a14..9197f386e 100644
--- a/addons.xml
+++ b/addons.xml
@@ -47,10 +47,12 @@
+
+
@@ -77,7 +79,10 @@
+
+
+
@@ -90,6 +95,8 @@
+
+
-
+
+
+
diff --git a/framework/entity/ResourceEntities.xml b/framework/entity/ResourceEntities.xml
index 349e5139a..e975c91ef 100644
--- a/framework/entity/ResourceEntities.xml
+++ b/framework/entity/ResourceEntities.xml
@@ -145,7 +145,7 @@ along with this software (see the LICENSE.md file). If not, see
-
+
@@ -186,6 +186,7 @@ along with this software (see the LICENSE.md file). If not, see
+ The date/time a blog post within a category was sent by email or other means.
diff --git a/framework/entity/ScreenEntities.xml b/framework/entity/ScreenEntities.xml
index 7f04eb37f..cc296a3e1 100644
--- a/framework/entity/ScreenEntities.xml
+++ b/framework/entity/ScreenEntities.xml
@@ -139,6 +139,7 @@ along with this software (see the LICENSE.md file). If not, see
+
diff --git a/framework/entity/SecurityEntities.xml b/framework/entity/SecurityEntities.xml
index 71cc6405b..e5e7f8a26 100644
--- a/framework/entity/SecurityEntities.xml
+++ b/framework/entity/SecurityEntities.xml
@@ -513,6 +513,7 @@ along with this software (see the LICENSE.md file). If not, see
+
diff --git a/framework/entity/ServerEntities.xml b/framework/entity/ServerEntities.xml
index f6f0481c9..e9b63af25 100644
--- a/framework/entity/ServerEntities.xml
+++ b/framework/entity/ServerEntities.xml
@@ -116,9 +116,9 @@ along with this software (see the LICENSE.md file). If not, see
-
+
-
+
@@ -196,6 +196,9 @@ along with this software (see the LICENSE.md file). If not, see
+
+
+
diff --git a/framework/entity/ServiceEntities.xml b/framework/entity/ServiceEntities.xml
index 81696e90f..7b51a3ab3 100644
--- a/framework/entity/ServiceEntities.xml
+++ b/framework/entity/ServiceEntities.xml
@@ -383,6 +383,7 @@ along with this software (see the LICENSE.md file). If not, see
+
diff --git a/framework/service/org/moqui/impl/EntitySyncServices.xml b/framework/service/org/moqui/impl/EntitySyncServices.xml
index bb0d8cad1..098bdf39d 100644
--- a/framework/service/org/moqui/impl/EntitySyncServices.xml
+++ b/framework/service/org/moqui/impl/EntitySyncServices.xml
@@ -236,13 +236,10 @@ along with this software (see the LICENSE.md file). If not, see
// ec.logger.warn("=========== get#EntitySyncData entityName=${entryMap.entityName} count=${currentCount} find=${find}")
if (currentCount > 0) {
- EntityListIterator resultEli = find.iterator()
- try {
+ find.iterator().withCloseable ({resultEli ->
int levels = entryMap.dependents ? 2 : 0
resultEli.writeXmlText((Writer) entityWriter, null, levels)
- } finally {
- resultEli.close()
- }
+ })
}
}
diff --git a/framework/service/org/moqui/impl/InstanceServices.xml b/framework/service/org/moqui/impl/InstanceServices.xml
index 7071d77fa..dacbd18ca 100644
--- a/framework/service/org/moqui/impl/InstanceServices.xml
+++ b/framework/service/org/moqui/impl/InstanceServices.xml
@@ -214,8 +214,13 @@ along with this software (see the LICENSE.md file). If not, see
-
-
+
+
+
@@ -281,8 +286,9 @@ along with this software (see the LICENSE.md file). If not, see
- https://docs.docker.com/engine/security/https/
-->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Authentication code is not valid
+
+
+
+
+
+
+
+
@@ -377,7 +411,7 @@ along with this software (see the LICENSE.md file). If not, see
- A reset password was sent by email to ${userAccount.emailAddress}. This password may only be used to change your password. Your current password is still valid.
+ A reset password was sent to the email of username ${userAccount.username}. This password may only be used to change your password. Your current password is still valid.
You must change your password before login.
diff --git a/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionFacadeImpl.groovy b/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionFacadeImpl.groovy
index 82e9acb3d..5edf7ab96 100644
--- a/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionFacadeImpl.groovy
+++ b/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionFacadeImpl.groovy
@@ -172,6 +172,10 @@ class ArtifactExecutionFacadeImpl implements ArtifactExecutionFacade {
return sw.toString()
}
+ ArtifactExecutionInfoImpl.ArtifactTypeStats getArtifactTypeStats() {
+ return ArtifactExecutionInfoImpl.getArtifactTypeStats(artifactExecutionInfoHistory)
+ }
+
void logProfilingDetail() {
if (!logger.isInfoEnabled()) return
diff --git a/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionInfoImpl.java b/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionInfoImpl.java
index 5880cf390..67fe40d54 100644
--- a/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionInfoImpl.java
+++ b/framework/src/main/groovy/org/moqui/impl/context/ArtifactExecutionInfoImpl.java
@@ -17,6 +17,8 @@
import org.moqui.impl.entity.EntityValueBase;
import org.moqui.util.CollectionUtilities;
import org.moqui.util.StringUtilities;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.StringWriter;
@@ -26,6 +28,7 @@
import java.util.*;
public class ArtifactExecutionInfoImpl implements ArtifactExecutionInfo {
+ protected final static Logger logger = LoggerFactory.getLogger(ArtifactExecutionInfoImpl.class);
// NOTE: these need to be in a Map instead of the DB because Enumeration records may not yet be loaded
private final static Map artifactTypeDescriptionMap = new EnumMap<>(ArtifactType.class);
@@ -153,6 +156,7 @@ public void copyAuthorizedInfo(ArtifactExecutionInfoImpl aeii) {
@Override
public long getRunningTime() { return endTimeNanos != 0 ? endTimeNanos - startTimeNanos : 0; }
public double getRunningTimeMillisDouble() { return (endTimeNanos != 0 ? endTimeNanos - startTimeNanos : 0) / 1000000.0; }
+ public long getRunningTimeMillisLong() { return Math.round((endTimeNanos != 0 ? endTimeNanos - startTimeNanos : 0) / 1000000.0); }
private void calcChildTime(boolean recurse) {
childrenRunningTime = 0;
if (childList != null) for (ArtifactExecutionInfoImpl aeii: childList) {
@@ -211,6 +215,128 @@ public void print(Writer writer, int level, boolean children) {
}
private String getKeyString() { return nameInternal + ":" + internalTypeEnum.name() + ":" + internalActionEnum.name() + ":" + actionDetail; }
+ private String getKeyStringNoName() { return internalTypeEnum.name() + ":" + internalActionEnum.name() + ":" + actionDetail; }
+
+ public static class ArtifactTypeStats {
+
+ public int screenCount = 0, screenTransCount = 0, screenContentCount = 0, restPathCount = 0,
+ serviceViewCount = 0, serviceOtherCount = 0,
+ entityFindOneCount = 0, entityFindListCount = 0, entityFindIteratorCount = 0, entityFindCountCount = 0,
+ entityCreateCount = 0, entityUpdateCount = 0, entityDeleteCount = 0;
+ public long screenTime = 0, screenTransTime = 0, screenContentTime = 0, restPathTime = 0,
+ serviceViewTime = 0, serviceOtherTime = 0,
+ entityFindOneTime = 0, entityFindListTime = 0, entityFindIteratorTime = 0, entityFindCountTime = 0,
+ entityCreateTime = 0, entityUpdateTime = 0, entityDeleteTime = 0;
+ public void add(ArtifactTypeStats that) {
+ if (that == null) return;
+
+ screenCount += that.screenCount; screenTransCount += that.screenTransCount;
+ screenContentCount += that.screenContentCount; restPathCount += that.restPathCount;
+ serviceViewCount += that.serviceViewCount; serviceOtherCount += that.serviceOtherCount;
+ entityFindOneCount += that.entityFindOneCount; entityFindListCount += that.entityFindListCount;
+ entityFindIteratorCount += that.entityFindIteratorCount; entityFindCountCount += that.entityFindCountCount;
+ entityCreateCount += that.entityCreateCount; entityUpdateCount += that.entityUpdateCount;
+ entityDeleteCount += that.entityDeleteCount;
+
+ screenTime += that.screenTime; screenTransTime += that.screenTransTime;
+ screenContentTime += that.screenContentTime; restPathTime += that.restPathTime;
+ serviceViewTime += that.serviceViewTime; serviceOtherTime += that.serviceOtherTime;
+ entityFindOneTime += that.entityFindOneTime; entityFindListTime += that.entityFindListTime;
+ entityFindIteratorTime += that.entityFindIteratorTime; entityFindCountTime += that.entityFindCountTime;
+ entityCreateTime += that.entityCreateTime; entityUpdateTime += that.entityUpdateTime;
+ entityDeleteTime += that.entityDeleteTime;
+ }
+ public ArtifactTypeStats cloneStats(ArtifactTypeStats that) {
+ ArtifactTypeStats newStats = new ArtifactTypeStats();
+ newStats.add(that);
+ return newStats;
+ }
+ }
+ static ArtifactTypeStats getArtifactTypeStats(ArrayList aeiiList) {
+ ArtifactTypeStats stats = new ArtifactTypeStats();
+ addArtifactTypeStats(aeiiList, stats);
+ return stats;
+ }
+ static void addArtifactTypeStats(ArrayList aeiiList, ArtifactTypeStats stats) {
+ if (aeiiList == null) return;
+ int aeiiListSize = aeiiList.size();
+ for (int i = 0; i < aeiiListSize; i++) {
+ ArtifactExecutionInfoImpl aeii = aeiiList.get(i);
+ // tight loop, use switch instead of if on these enums for much better performance; run fast for use in on the fly accumulators
+ switch (aeii.internalTypeEnum) {
+ case AT_ENTITY:
+ switch (aeii.internalActionEnum) {
+ case AUTHZA_VIEW:
+ if (aeii.actionDetail != null && !aeii.actionDetail.isEmpty()) {
+ char first = aeii.actionDetail.charAt(0);
+ switch (first) {
+ case 'o': // one
+ case 'r': // refresh
+ stats.entityFindOneCount++;
+ stats.entityFindOneTime += aeii.getRunningTime();
+ break;
+ case 'l': // list
+ stats.entityFindListCount++;
+ stats.entityFindListTime += aeii.getRunningTime();
+ break;
+ case 'i': // iterator
+ stats.entityFindIteratorCount++;
+ stats.entityFindIteratorTime += aeii.getRunningTime();
+ break;
+ case 'c': // count
+ stats.entityFindCountCount++;
+ stats.entityFindCountTime += aeii.getRunningTime();
+ break;
+ }
+ } else {
+ logger.warn("entity view with no detail " + aeii.toBasicString());
+ }
+ break;
+ case AUTHZA_CREATE:
+ stats.entityCreateCount++;
+ stats.entityCreateTime += aeii.getRunningTime();
+ break;
+ case AUTHZA_UPDATE:
+ stats.entityUpdateCount++;
+ stats.entityUpdateTime += aeii.getRunningTime();
+ break;
+ case AUTHZA_DELETE:
+ stats.entityDeleteCount++;
+ stats.entityDeleteTime += aeii.getRunningTime();
+ break;
+ }
+ break;
+ case AT_SERVICE:
+ if (aeii.internalActionEnum == AUTHZA_VIEW) {
+ stats.serviceViewCount++;
+ stats.serviceViewTime += aeii.getRunningTime();
+ } else {
+ stats.serviceOtherCount++;
+ stats.serviceOtherTime += aeii.getRunningTime();
+ }
+ break;
+ case AT_XML_SCREEN:
+ stats.screenCount++;
+ stats.screenTime += aeii.getRunningTime();
+ break;
+ case AT_XML_SCREEN_TRANS:
+ stats.screenTransCount++;
+ stats.screenTransTime += aeii.getRunningTime();
+ break;
+ case AT_XML_SCREEN_CONTENT:
+ stats.screenContentCount++;
+ stats.screenContentTime += aeii.getRunningTime();
+ break;
+ case AT_REST_PATH:
+ stats.restPathCount++;
+ stats.restPathTime += aeii.getRunningTime();
+ break;
+ }
+
+ // this aeii is done, how about children?
+ addArtifactTypeStats(aeii.childList, stats);
+ }
+ }
@SuppressWarnings("unchecked")
static List